home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / iostrm.zip / IOSTREAM.TXT
Text File  |  1991-07-11  |  119KB  |  4,134 lines

  1.    This tutorial file is the second version of the notes that I wrote to
  2. attempt to explain how input and output are done in Borland C++ using the "new"
  3. streaming methods. (The first version was posted last January.)
  4.  
  5.    The tutorial consists of 5 chapters:
  6.  
  7.    1) Header file
  8.    2) Output
  9.    3) Input
  10.    4) Manipulators
  11.    5) File I/O
  12.  
  13. ============================================================================
  14. ============================================================================
  15.  
  16.                       CHAPTER 1 -- Header File
  17.  
  18.    All C++ program examples in this tutorial include a file called "header.h".
  19. Within this file are all of the system header files and other information
  20. needed to compile any particular program example from these chapters as well
  21. as other chapters. Obviously having all of these files slows down the
  22. compilation time, but it's not really noticeable if you are using the
  23. pre-compiled header option.
  24.  
  25.    A listing of the header file follows:
  26.  
  27. /*
  28.    My private header file for all C++ and C programs.
  29.  
  30.    Note this define:
  31.  
  32.      OBJECT_FILE -- ON if a program is being compiled normally
  33.                     using Borland C++. This prevents the code in the
  34.                     header file from being compiled (which would negate
  35.                     the whole purpose of using the pre-compiled header
  36.                     option)
  37.  
  38.                     OFF when it's only necessary to generate the .OBJ
  39.                     file for Borland C++ using a pseudo compilation. This
  40.                     .OBJ file will then be used by the linker.
  41. */
  42.  
  43. #ifndef HEADER_H
  44. #define HEADER_H
  45. #endif
  46.  
  47. #include <fstream.h>
  48. #include <iomanip.h>
  49. #include <strstream.h>
  50. #include <new.h>
  51. #include <alloc.h>
  52. #include <conio.h>
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <ctype.h>
  56. #include <stdlib.h>
  57. #include <math.h>
  58. #include <time.h>
  59. #include <limits.h>
  60. #include <dos.h>
  61.  
  62. //////////////////////////////////
  63. // My private defines
  64.  
  65. #define FALSE                 0
  66. #define TRUE                  !FALSE
  67. #define AND                   &&
  68. #define OR                    ||
  69. #define NO                    0
  70. #define YES                   !NO
  71. #define EQUALS                ==
  72. #define IS_EQUAL_TO           ==
  73. #define NOT                 !
  74. #define IS_NOT_EQUAL_TO       !=
  75. #define NOT_EQUAL_TO          !=
  76. //
  77. #define BLANK                 ' '
  78. #define SPACE                 ' '
  79. #define ASTERISK              '*'
  80. #define DECIMAL               '.'
  81. #define NEW_LINE              '\n'
  82. #define NEWLINE               '\n'
  83. #define NUL                   '\0'
  84. #define TAB                   '\t'
  85. #define BACKSPACE             '\b'
  86. #define BEEP                  '\a'
  87. #define FORMFEED              '\f'
  88. #define RETURN                '\r'
  89. #define SINGLE_QUOTE          '\''
  90. #define SINGLEQUOTE           '\''
  91. #define DOUBLE_QUOTE          '\"'
  92. #define DOUBLEQUOTE           '\"'
  93. #define BACK_SLASH            '\\'
  94. #define BACKSLASH             '\\'
  95.  
  96. // Declarations
  97.  
  98. void PAUSE() ;
  99. void IOFLAGS(istream& = cin) ;
  100. typedef void* POINTER ;
  101. const char* ADDRESS(POINTER) ;
  102. extern ofstream POUT ;
  103. void FORMATFLAGS(ostream& = cout) ;
  104. void _NEW_HANDLER() ;
  105. void SET_NEW_HANDLER() ;
  106. istream& FLUSH(istream& strm) ;
  107. ostream& PRINTER(ostream&) ;
  108. ostream& SCREEN(ostream&) ;
  109. ostream& LEFT(ostream& str) ;
  110. ostream& RIGHT(ostream& str) ;
  111. ostream& INTERNAL(ostream& str) ;
  112. ostream& SHOWPOINT(ostream& str) ;
  113. ostream& SHOWBASE(ostream& str) ;
  114. ostream& NOSHOWBASE(ostream& str) ;
  115. ostream& FIXED(ostream& str) ;
  116. ostream& SCIENTIFIC(ostream& str) ;
  117. ostream& UPPERCASE(ostream& str) ;
  118. ostream& LOWERCASE(ostream& str) ;
  119. ostream& SHOWPOS(ostream& str) ;
  120. ostream& NOSHOWPOS(ostream& str) ;
  121.  
  122. /////////////////////////////////////////////////////////////////
  123. // This part begins the actual code that cannot be part of the pre-compiled
  124. // headers that Borland C++ supports. For normal compilations the define
  125. // OBJECT_FILE must be ON
  126. /////////////////////////////////////////////////////////////////
  127.  
  128. #ifndef OBJECT_FILE
  129.  
  130. // My private PAUSE function
  131. void PAUSE()
  132. {
  133.    cout << "Press any key to continue...\n" ;
  134.    getch() ;
  135. }
  136.  
  137. // This function prints the various I/O flags of an input stream. Defaults
  138. // to 'cin'.
  139.  
  140. void IOFLAGS(istream& stream)
  141. {
  142.     cout << "eof state is  " << (stream.eof() ? "ON" : "OFF") << "\n" ;
  143.     cout << "good state is " << (stream.good() ? "ON" : "OFF") << "\n" ;
  144.     cout << "fail state is " << (stream.fail() ? "ON" : "OFF") << "\n" ;
  145.     cout << "bad state is  " << (stream.bad() ? "ON" : "OFF") << "\n" ;
  146.     cout << "if(!instance) returns " << (!stream ? "TRUE" : "FALSE") << "\n" ;
  147.     cout << "if(instance) returns " << (stream ? "TRUE" : "FALSE") << "\n" ;
  148. }
  149.  
  150. // A function to print an address in segment:offset form for Borland C++.
  151. // CAUTION: Do NOT call this function more than oncein a single statement, e.g.,
  152.  
  153. //   int n1 , n2 ;
  154. //   cout << ADDRESS(&n1) << endl << ADDRESS(&n2) << endl ;
  155.  
  156. const char* ADDRESS(POINTER add)
  157. {
  158.    static char buffer[15] ;
  159.    ostrstream output(buffer , sizeof buffer) ;
  160.    output.fill('0') ;
  161.    output << setw(4) << FP_SEG(add) << ':'
  162.           << setw(4) << FP_OFF(add) << ends ;
  163.    return buffer ;
  164. }
  165.  
  166. // Functions to handle an out-of-memory condition
  167.  
  168. void _NEW_HANDLER()
  169. {
  170.    cout << "MEMORY ALLOCATION ERROR\n" ;
  171.    cout << coreleft() << " bytes remaining\n" ;
  172.    PAUSE() ;
  173.    cout << "Returning to DOS...\n" ;
  174.    exit(1) ;
  175. }
  176.  
  177. void SET_NEW_HANDLER()
  178. {
  179.    _new_handler = _NEW_HANDLER ;
  180. }
  181.  
  182. // This function prints the format flags
  183. // of an output stream. The default is
  184. // "cout"
  185.  
  186. void FORMATFLAGS(ostream& stream)
  187. {
  188.    static char* message[] =
  189.    {
  190.      "skipsw" ,
  191.      "left" ,
  192.      "right" ,
  193.      "internal" ,
  194.      "dec" ,
  195.      "oct" ,
  196.      "hex" ,
  197.      "showbase" ,
  198.      "showpoint" ,
  199.      "uppercase" ,
  200.      "showpos" ,
  201.      "scientific" ,
  202.      "fixed" ,
  203.      "unitbuf" ,
  204.      "stdio"
  205.    } ;
  206.  
  207.    cout << "FORMAT FLAGS\n" ;
  208.    long f = stream.flags() ;
  209.    for(int i = 0 ; i < 16 ; ++i)
  210.    {
  211.      if(f & 0x0001)
  212.         cout << message[i] << "\n" ;
  213.       f >>= 1 ;
  214.    }
  215. }
  216.  
  217. // My private flush-the-input-buffer manipulator
  218.  
  219. istream& FLUSH(istream& strm)
  220. {
  221.    // Reset the error state
  222.    strm.clear() ;
  223.  
  224.    // Two different types of flushing
  225.    // are possible: keyboard and file
  226.  
  227.    // If the keyboard is being used,
  228.    // simply flush all characters
  229.    if(&strm EQUALS &cin)
  230.    {
  231.       // Find out how many characters remain in the stream
  232.       int remain = strm.rdbuf()->in_avail() ;
  233.       while(remain--)
  234.           strm.get() ;
  235.    }
  236.  
  237.    // If a disk file is being used, flush while characters remain or
  238.    // until '\n' or EOF is found
  239.    else
  240.    {
  241.       char ch ;
  242.       while(strm.get(ch) AND ch != '\n' AND ch != EOF)
  243.           continue ;
  244.    }
  245.  
  246.    // Reset the error state again
  247.    strm.clear() ;
  248.  
  249.    return strm ;
  250. }
  251.  
  252. // Define a global instance of the class 'ofstream' called POUT that
  253. // can be tied to a DOS printer
  254.  
  255. ofstream POUT("prn") ;
  256.  
  257. // A manipulator that directs to the printer all subsequent output for
  258. // the one statement in which it is found
  259.  
  260. ostream& PRINTER(ostream&)
  261. {
  262.    return POUT ;
  263. }
  264.  
  265. // A manipulator that directs to the screen all subsequent output for
  266. // the one statement in which it is found
  267.  
  268. ostream& SCREEN(ostream&)
  269. {
  270.    return cout ;
  271. }
  272.  
  273. // A manipluator to set left justification
  274.  
  275. ostream& LEFT(ostream& str)
  276. {
  277.    str.setf(ios::left , ios::adjustfield) ;
  278.    return str ;
  279. }
  280.  
  281. // A manipluator to set right justification
  282.  
  283. ostream& RIGHT(ostream& str)
  284. {
  285.    str.setf(ios::right , ios::adjustfield) ;
  286.    return str ;
  287. }
  288.  
  289. // A manipluator to set internal justification
  290.  
  291. ostream& INTERNAL(ostream& str)
  292. {
  293.    str.setf(ios::internal , ios::adjustfield) ;
  294.    return str ;
  295. }
  296.  
  297. // A manipulator to show the decimal point
  298.  
  299. ostream& SHOWPOINT(ostream& str)
  300. {
  301.    str.setf(ios::showpoint) ;
  302.    return str ;
  303. }
  304.  
  305. // A manipulator to show the base on hex and octal output
  306.  
  307. ostream& SHOWBASE(ostream& str)
  308. {
  309.    str.setf(ios::showbase) ;
  310.    return str ;
  311. }
  312.  
  313. // A manipulator to suppress the showing of the base
  314.  
  315. ostream& NOSHOWBASE(ostream& str)
  316. {
  317.    str.unsetf(ios::showbase) ;
  318.    return str ;
  319. }
  320.  
  321. // A manipulator to show fixed point output
  322.  
  323. ostream& FIXED(ostream& str)
  324. {
  325.    str.setf(ios::fixed , ios::floatfield) ;
  326.    return str ;
  327. }
  328.  
  329. // A manipulator to show scientific point output
  330.  
  331. ostream& SCIENTIFIC(ostream& str)
  332. {
  333.    str.setf(ios::scientific , ios::floatfield) ;
  334.    return str ;
  335. }
  336.  
  337. // A manipulator to show uppercase output on hex and scientific numbers
  338.  
  339. ostream& UPPERCASE(ostream& str)
  340. {
  341.    str.setf(ios::uppercase) ;
  342.    return str ;
  343. }
  344.  
  345. // A manipulator to show lowercase output on hex and scientific numbers
  346.  
  347. ostream& LOWERCASE(ostream& str)
  348. {
  349.    str.unsetf(ios::uppercase) ;
  350.    return str ;
  351. }
  352.  
  353. // A manipulator to show a '+' on positive numbers
  354.  
  355. ostream& SHOWPOS(ostream& str)
  356. {
  357.    str.setf(ios::showpos) ;
  358.    return str ;
  359. }
  360.  
  361. // A manipulator to negate showing a '+' on positive numbers
  362.  
  363. ostream& NOSHOWPOS(ostream& str)
  364. {
  365.    str.unsetf(ios::showpos) ;
  366.    return str ;
  367. }
  368.  
  369. #endif
  370.  
  371. ============================================================================
  372. ============================================================================
  373.  
  374.                       CHAPTER 2 -- Output
  375.  
  376.  
  377. Introduction
  378.  
  379.    Whenever data gets sent to a text output device, it takes on the form
  380. of a stream of characters. For example, the floating point number 1.234 is
  381. not stored internally as 5 characters ('1' , '.' , '2' , '3' , '4'), but
  382. rather in a special format designed to accommodate floating point values.
  383. In character format, this value is meaningless. Yet, if you were to print
  384. this number, you certainly would want to have the aforementioned 5
  385. characters appear on your output device.
  386.  
  387.    The C++ input/output mechanism provided with AT&T release 2.0 provides
  388. a series of classes that have been created to handle the problem of
  389. sending and receiving data. This mechanism consists of many classes, some
  390. derived from others, and some contained within others. All of these
  391. classes are contained within a library caled iostream, and can be
  392. accessed by your program by writing:
  393.  
  394.        #include <iostream.h>
  395.  
  396.    A good explanation of how streams operate comes from Bryan Flamig,
  397. Turbo C++, A Self-Teaching Guide, page 326:
  398.  
  399.        Even though the stdio library provides for stream-oriented I/O, the
  400.        iostream library takes advantage of the powerful objected-oriented
  401.        features of C++, and implements the stream I/O in a manner closer to the
  402.        conceptual stream model.
  403.  
  404.        For example, consider the following call to the stdio printf() routine,
  405.        which inserts some data into the stdin stream:
  406.  
  407.               int x = 42 ;
  408.               printf ("The answer is:%d" , x) ;
  409.  
  410.        With calls like this to printf(), you still think in terms of procedural
  411.        programming. It's hard to conceptualize the stream model here. There are
  412.        really two pieces of data being written, a character string "The answer
  413.        is:", and the number 42. Yet the output of these pieces is lumped
  414.        together into one function call.
  415.  
  416.        In contrast, with the iostream library, you think in terms of stream
  417.        objects, and operators acting upon those objects. You read and write to
  418.        stream objects piece by piece. For instance, the following code shows how
  419.        to generate the equivalent output for our example, using the iostream
  420.        library:
  421.  
  422.               int x = 42 ;
  423.               cout << "The answer is: " << x ;
  424.  
  425.        In this statement, cout is a stream object that's analogous to stdout.
  426.        The left-shift operator << has been overloaded, and is used to insert
  427.        data into the stream. The direction of the arrow suggests the direction
  428.        of data flow into the stream object: first the character string is
  429.        inserted, and then the number 42.
  430.  
  431. ==========================================================
  432.  
  433. How to do simple output
  434.  
  435.    At the lowest level, the most fundamental operation is to manipulate
  436. the characters within some buffer, also known as a stream. This is done by
  437. the class streambuf. There are two other classes derived from
  438. streambuf: filebuf, which handles file-specific buffer operations, and
  439. strstreambuf, which performs in-memory I/O buffering.
  440.  
  441.    Because input and output must be formatted to be legible, another class
  442. called ios contains functions and data to handle this task. When an
  443. instance of the class ios comes into existence, it receives a pointer to
  444. some streambuf area. To send the actual formatted output to the user,
  445. another class called ostream (which is derived from ios) is used.
  446.  
  447. Classes, like built-in (scalar) types, do not occupy any memory. What is
  448. needed, then, is an instance, or object, of that class type. In the
  449. hierarchy of derivation, the last class, ostream, is the one that used to
  450. create the instance, as follows:
  451.  
  452.         ostream cout ;
  453.  
  454.    Since the instance cout is an instance of a class that has been
  455. derived from parent classes, by definition it has inherited all of the
  456. data members of its parent classes, and has all of the functionality of
  457. those classes. Also, since this instance is defined at global scope, your
  458. program has unlimited access to it at all times. Output operations are
  459. initiated using the instance cout.
  460.  
  461.    In addition to data members, classes can contain functions to operate
  462. upon these members. In the class ostream, the function you will use the
  463. most often is called the insertion operator, and its name is operator<<.
  464. The argument to this function is the data item that you wish to output.
  465. The name ╥insertion╙ comes from the fact that you are ╥inserting╙ items
  466. into an output buffer.
  467.  
  468.    In a manner similar to that of accessing a function member of any user-
  469. defined class, function members of class ostream are also accessed using
  470. the direct member operator (the dot operator). This is done by first
  471. writing the instance, followed by the dot operator, and then the function
  472. name with any arguments enclosed within parentheses. For example, to
  473. output a simple message, you would code:
  474.  
  475.        cout.operator<<("THE ANSWER IS ") ;
  476.  
  477. where "THE ANSWER IS " is the argument to the function operator<<.
  478. Similarly, to output the number 65, you would code:
  479.  
  480.        cout.operator<<(65) ;
  481.  
  482. To output a new-line character, you would code:
  483.  
  484.        cout.operator<<('\n') ;
  485.  
  486. or, if you wish, a string containing nothing but a new-line character:
  487.  
  488.        cout.operator<<("\n") ;
  489.  
  490.    If you really think about it, you should be asking the obvious
  491. question, how can a function take a single argument of different types?
  492. In other words, in the first call above a string (type char*) was passed
  493. as the argument, in the second call an integer (type int) was passed, and
  494. in the third a character (type char) was passed. How can this be? The
  495. answer is that the function operator<< has been overloaded, so that many
  496. versions of the same function exist within the class ostream. The
  497. compiler is smart enough to distinguish one version from another (through
  498. a process known as argument matching), so that your function call
  499. correctly accesses the function specifically written to handle the type of
  500. argument that you provide.
  501.  
  502. Concatenating function calls
  503.  
  504.    The next obvious question you should be asking is whether you have to
  505. code a series of such function calls if more than one data item is to be
  506. output. In other words, in the examples above, are three separate function
  507. calls really necessary? Fortunately, the answer is no. The way the
  508. operator<< function is written, a reference (address) to the calling
  509. instance (cout) is returned by the function, and can therefore be used as
  510. the calling instance for a concatenated function call. That is, the three
  511. function calls can be written:
  512.  
  513.         cout.operator<<("THE ANSWER IS ").operator<<(65).operator<<('\n') ;
  514.  
  515.    That's the good news. The bad news is that it's still too much coding
  516. and still too awkward. With this in mind, the designers of C++ allow the
  517. programmer to abbreviate the notation:
  518.  
  519.         cout.operator<<(argument1) ;
  520.  
  521. with the more convenient:
  522.  
  523.         cout << argument1 ;
  524.  
  525. and the notation:
  526.  
  527.         cout.operator<<(argument1).operator<<(argument2) ;
  528.  
  529. with the more convenient:
  530.  
  531.         cout << argument1 << argument2 ;
  532.  
  533. As you can see, the dot operator has been eliminated, and the function
  534. operator<<() has been replaced with just the insertion operator <<.
  535.  
  536.    Note that the operator << in this context is the same operator that is
  537. used to shift bits to the left. This illustrates the C++ technique of
  538. operator overloading. Fortunately, the compiler infers the proper usage
  539. from the context in which the operator is located. In other words,
  540.  
  541.         cout << 1 ;     // Output the constant 1 to the screen
  542.         number << 1 ;   // Shift 'number' 1 bit to the left
  543.  
  544.    Since white space in your program is ignored by the compiler, for
  545. stylistic purposes you could write each insertion operator on its own
  546. line. Try running this program.
  547.  
  548.     // EXAMPLE OUTPUT-01
  549.  
  550.     #include <header.h>
  551.  
  552.     int main()
  553.     {
  554.           cout << "THE ANSWER IS "
  555.                << 65
  556.                 << "\n" ;
  557.  
  558.        return 0 ;
  559.     }
  560.  
  561. ==========================================================
  562.  
  563. Note that only one such occurrence of cout needed to be written until the
  564. end of the statement is reached.
  565.  
  566.    Of course, you could restrict each statement to having just one
  567. insertion operator. This program produces exactly the same output as
  568. before.
  569.  
  570.     // EXAMPLE OUTPUT-02
  571.  
  572.     #include <header.h>
  573.  
  574.     int main()
  575.     {
  576.           cout << "THE ANSWER IS " ;
  577.            cout << 65 ;
  578.           cout << "\n" ;
  579.  
  580.         return 0 ;
  581.     }
  582.  
  583. ==========================================================
  584.  
  585.    In addition to a string, an integer, and a character, the function
  586. operator<< has been overloaded to accept arguments of type long, float,
  587. double, pointer, and so forth. In other words, all of the primitive types
  588. can easily be output.
  589.  
  590.    When overloading a built-in operator, you cannot change its precedence,
  591. and since the operator << has lower precendence than the arithmetic
  592. operators, statements such as:
  593.  
  594.     cout << 1 + 2 ;
  595.     cout << 2 * 3 ;
  596.     cout << number++ ;
  597.  
  598. pose no problem because the arithmetice is done first. However, a fragment
  599. such as:
  600.  
  601.     cout << 123 ? 1 : 0 ;
  602.  
  603. will output the number 123 instead of the number 1 because the line is
  604. interpreted as:
  605.  
  606.     (cout << 123) ? 1 : 0 ;
  607.  
  608. since << has higher precedence than the conditional operator. Then the
  609. conditional operator is executed, but the result doesn't do anything
  610. useful.
  611.  
  612.    Another place to go wrong is with the use of function calls embedded in
  613. a series of calls to operator<<. There is no guarantee of the order of
  614. evaluation of items within an expression. Normally this does not pose a
  615. problem, unless the function affects the state of the output stream.
  616.  
  617. // EXAMPLE OUTPUT-03
  618.  
  619. // CAUTION: DON'T USE FUNCTION
  620. // CALLS THAT AFFECT THE STATE
  621. // OF THE OUTPUT STREAM
  622.  
  623. #include <header.h>
  624.  
  625. int f1()
  626. {
  627.    cout << "Item 1\n" ;
  628.    return 1 ;
  629. }
  630.  
  631. int f2()
  632. {
  633.    cout << "Item 2\n" ;
  634.    return 2 ;
  635. }
  636.  
  637. int f3()
  638. {
  639.    cout << "Item 3\n" ;
  640.    return 3 ;
  641. }
  642.  
  643. ///////////////////////////////////
  644.  
  645. int main()
  646. {
  647.    cout << f1() << '\n'
  648.         << f2() << '\n'
  649.         << f3() << '\n' ;
  650.  
  651.    return 0 ;
  652. }
  653.  
  654. The output of this program is:
  655.  
  656.     Item 3
  657.     Item 2
  658.     Item1
  659.     1
  660.     2
  661.     3
  662.  
  663. ==========================================================
  664.  
  665. Bit format flags
  666.  
  667.    Now think about a printf() function call. It usually consists of a
  668. control string argument and, optionally, a list of expressions to be
  669. output. The control string contains literals which will be output exactly
  670. as shown, and conversion specifications that indicate exactly how an
  671. expression from the list of expressions is to appear. Each conversion
  672. specification starts with a % and ends with a conversion character, e.g.,
  673. d for decimal format, c for character format, s for a string, etc.
  674. Between the start and end you may enter various flags, the field width,
  675. base formatting, justification, floating point precision, and so forth.
  676. Each conversion specification stands on its own; there is no connection to
  677. any other one.
  678.  
  679.    In the C++ AT&T version 2.0 stream I/O, all of the characteristics
  680. relating to how an expression should appear apply, not to each individual
  681. expression, but to the output stream as a whole. In other words, once you
  682. specify that decimal format is desired, all integer numbers from that
  683. point on are output in decimal format. No further action need be taken. If
  684. you decide to switch to hexadecimal output, then all integer numbers from
  685. that point on will be shown in their hex formats. The same is true for
  686. floating point precision. Once it is set, it stays set for all subsequent
  687. floating point numbers. (There is one important exception to the ╥set it
  688. and forget it╙ feature of C++ streaming that will be discussed later).
  689.  
  690.    Any binary characteristic of the output stream is stored in a long
  691. (protected) field in the class ios. In Borland C++ this field is called
  692. x_flags. (The fact that it's protected means that you cannot access it
  693. directly, as though it were private.) Each characteristic occupies one
  694. bit of this field, which simply means that it's either true or false; on
  695. or off; set or not set. For example, the output state of decimal is either
  696. on or off. The same can be said for the output states of hexadecimal and
  697. octal. Also, the state of left-justification is either set or not set, as
  698. is its opposite, right-justification. On the other hand, stream
  699. characteristics that require values, such as the field width and floating
  700. point precision, are stored in (protected) integer variables.
  701.  
  702.    Each binary characteristic is represented by a unique value in a field
  703. that defines an unnamed public enumerated type in the class ios. Note
  704. that such enumerated types, while still being within the scope of the
  705. class, do not necessarily have to be referenced via instances of the
  706. class. Instead, they may be referenced using explicit qualification, i.e.,
  707. the class name with the scope resolution operator. The name of the
  708. enumerated value itself is also local to the class. Each value is
  709. represented by exactly one bit in the field, and no two fields ever have
  710. the same bit on. Thus, no two characteristics will ever have the same bit
  711. position (ranging from 15 down to 0) set on. By ORing these bits into the
  712. field x_flags, the different states can be set with no conflict. This
  713. allows someone examining the field x_flags to infer with no ambiguity
  714. which characteristics are on and which are off.
  715.  
  716.    Each binary characteristic also has a name associated with it that you
  717. may reference. The complete list of all enumerated values is shown below.
  718. To repeat: Because these names exist within the class ios, the name of
  719. this class must be specified in conjunction with the scope resolution
  720. operator (::) to unambiguously access a specific value. These are the
  721. names and values that Borland uses:
  722.  
  723.   NAME            VALUE     MEANING
  724.  
  725.   ios::skipws     0x0001    Skip whitespace on input
  726.   ios::left       0x0002    Left-justification of output
  727.   ios::right      0x0004    Right-justification of output
  728.   ios::internal   0x0008    Pad after sign or base indicator
  729.   ios::dec        0x0010    Show integers in decimal format
  730.   ios::oct        0x0020    Show integers in octal format
  731.   ios::hex        0x0040    Show integers in hexadecimal format
  732.   ios::showbase   0x0080    Show the base for octal and hex numbers
  733.   ios::showpoint  0x0100    Ensure that the decimal point is
  734.                             shown for all floating point numbers
  735.   ios::uppercase  0x0200    Show uppercase hex numbers
  736.   ios::showpos    0x0400    Show + for positive numbers
  737.   ios::scientific 0x0800    Use exponential notation on floating point numbers
  738.   ios::fixed      0x1000    Use fixed decimal output on floating point numbers
  739.   ios::unitbuf    0x2000    Flush all streams after insertion
  740.   ios::stdio      0x4000    Flush stdout and stderr after insertion
  741.  
  742.    Because we will be examining these bits very carefully in the coming
  743. examples, it is very useful to have a function to clearly display the
  744. status for us. This has been done in the function FORMATFLAGS() which is
  745. contained in the file header.h. This function takes one argument: an
  746. instance of an output stream. If no argument is supplied, then the
  747. function defaults to using the name cout.
  748.  
  749. Try running this test. Are any of these enumerated bits in the field
  750. x_flags already on when your program first gets control? This little
  751. program will provide the answer.
  752.  
  753.     // EXAMPLE OUTPUT-11
  754.  
  755.     // TEST THE DEFAULT OF x_flags
  756.  
  757.     #include <header.h>
  758.  
  759.     int main()
  760.     {
  761.           FORMATFLAGS() ;
  762.  
  763.        return 0 ;
  764.     }
  765.  
  766. The output of this program is:
  767.  
  768.     FORMAT FLAGS
  769.     skipws
  770.     unitbuf
  771.  
  772. Therefore, by default white space is skipped when doing input, and all
  773. streams are automatically flushed after each insertion. (NOTE: Refer to
  774. the chapter INPUT for an explanation of the skipws bit, and the chapter
  775. MANIP for an explanation of the unitbuf bit.)
  776.  
  777. Manipulating the bit format flags
  778.  
  779.    The next item of concern is how to turn these settings on and off.
  780. Within the class ios there are several member functions provided that
  781. allow this to be done. The first of these functions is called setf().
  782. Remember: to call it, you must first specify the instance name, cout, the
  783. dot member operator, and then the function name. Thus, you would write:
  784.  
  785.      cout.setf( /* arguments */ ) ;
  786.  
  787.    The function setf() has been overloaded to accept either one or two
  788. arguments. In both cases, the first argument specifies which bits are to
  789. be turned ON in the field x_flags.
  790.  
  791.    For example, to turn on the ios::dec bit, you would code:
  792.  
  793.     cout.setf(ios::dec) ;
  794.  
  795. The function setf() works by ORing its first argument into the field
  796. x_flags, thereby leaving any other bits in this field undisturbed. This
  797. means that it's possible to turn on more than one bit with just one call
  798. to setf by using an expression for the first argument that contains
  799. several bits ORed together. For example, to turn on the ios::dec and the
  800. ios::right bits, you would code:
  801.  
  802.     cout.setf(ios::dec | ios::right) ;
  803.  
  804.    How can you turn the bits off? Use the member function unsetf(). This
  805. function takes exactly one argument: the bit pattern to be turned off.
  806. Thus, to turn off the bit ios::dec, you would code:
  807.  
  808.     cout.unsetf(ios::dec) ;
  809.  
  810. Like setf(), more than one bit at a time can be turned off by ORing the
  811. enumerated values together in the argument field.
  812.  
  813.    Unfortunately, the previous method of turning bits on and off is
  814. awkward because in many cases the bits are mutually exclusive, and it
  815. would normally take 2 function calls to (1) turn a bit off using
  816. unsetf(), and (2) turn another bit on using setf(). Fortunately, a
  817. better way exists by using the setf() function with 2 arguments. In this
  818. case the second argument represents those specific bits which are to be
  819. turned OFF just prior to having those bits turned ON that are specified by
  820. the bitwise AND of the first and second arguments. For example, to turn
  821. the bit ios::dec ON and ensure that the (mutually exclusive) bits
  822. ios::oct and ios::hex are OFF, you would code:
  823.  
  824.   cout.setf(ios::dec , ios::dec | ios::oct | ios::hex) ;
  825.  
  826. To prove this, run this program:
  827.  
  828.     // EXAMPLE OUTPUT-12
  829.  
  830.     // TEST TURNING ON FORMAT FLAG BITS
  831.  
  832.     #include <header.h>
  833.  
  834.     int main()
  835.     {
  836.        cout.setf(ios::oct | ios::hex) ;
  837.         FORMATFLAGS() ;
  838.      cout.setf(ios::dec , ios::dec | ios::oct | ios::hex) ;
  839.        FORMATFLAGS() ;
  840.  
  841.        return 0 ;
  842.     }
  843.  
  844. The output of this program is:
  845.  
  846.     FORMAT FLAGS
  847.     skipws
  848.     oct
  849.     hex
  850.     unitbuf
  851.     FORMAT FLAGS
  852.     skipws
  853.     dec
  854.     unitbuf
  855.  
  856. ==========================================================
  857.  
  858.    Because ios::dec, ios::oct and ios::hex are mutually exclusive bit
  859. fields (that is, you only want one of them on at any time), you would
  860. normally AND the one bit of the first argument of setf() with the OR of
  861. all 3 bits, as shown above. The second argument can also be specified as
  862. ios::basefield, where this value is pre-defined as:
  863.  
  864.    ios::dec | ios::oct | ios::hex.
  865.  
  866.    For example, program OUTPUT-12 can be re-written as:
  867.  
  868.     // EXAMPLE OUTPUT-13
  869.  
  870.     // TEST ios::basefield
  871.  
  872.     #include <header.h>
  873.  
  874.     int main()
  875.     {
  876.         cout.setf(ios::oct | ios::hex) ;
  877.        FORMATFLAGS() ;
  878.        cout.setf(ios::dec , ios::basefield) ;
  879.        FORMATFLAGS() ;
  880.  
  881.        return 0 ;
  882.     }
  883.  
  884. The output of this program is the same.
  885.  
  886. ==========================================================
  887.  
  888.    In a similar manner, the field ios::adjustfield represents the bit
  889. positions of ios::left, ios::right and ios::internal ORed together,
  890. and the field ios::floatfield represents the bit positions of
  891. ios::fixed and ios::scientific ORed together.
  892.  
  893.    Because the field x_flags in the class ios is protected, you cannot
  894. access it directly. However, there is a public member function called
  895. flags() that will return this field to you. If you provide a long
  896. integer as an argument to flags(), then the existing value of x_flags
  897. will be returned to you after your argument is used to provide a new
  898. setting for x_flags. For example:
  899.  
  900.     // EXAMPLE OUTPUT-14
  901.  
  902.     // TEST THE flags() MEMBER FUNCTION
  903.  
  904.     #include <header.h>
  905.  
  906.     int main()
  907.     {
  908.      long value = cout.flags(0) ;
  909.      cout.setf(ios::hex , ios::basefield) ;
  910.         cout << "value is "
  911.           << value
  912.           << '\n' ;
  913.      FORMATFLAGS(cout) ;
  914.  
  915.        return 0 ;
  916.     }
  917.  
  918. The output of this program is:
  919.  
  920.     value is 2001
  921.     FORMAT FLAGS
  922.     hex
  923.  
  924. ==========================================================
  925.  
  926. Note that value is the old value of x_flags, and is printed in
  927. hexadecimal. The '2' represents the unitbuf bit, and the '1' is the
  928. skipws bit. There is nothing shown under the heading FORMAT FLAGS
  929. except hex because all of the bits were turned off by the call to flags,
  930. then the hex bit was turned back on.
  931.  
  932.    Both the setf() and unsetf() functions return a value, which you are
  933. free to use or ignore. The value returned is a long integer representing
  934. the previous value of the field x_flags. However, you will probably never
  935. have occasion to use this value.
  936.  
  937. ==========================================================
  938.  
  939. The base setting and integer output
  940.  
  941.    Output formatting is important because you want to have complete
  942. flexibility in the manner in which your data appears. Let's start with the
  943. base in which integers will be shown. If a printf() function call, you
  944. have 3 choices: decimal, octal and hex. A decimal output can be obtained
  945. by using a conversion specification of %d or %i, an octal by using %o,
  946. and hex by using %x or %X. (How to emulate lower vs. upper case will be
  947. discussed later.) There are 3 bits in the enumerated values shown in the
  948. Bit Format Flags section that control the base setting:
  949.  
  950.     ios::dec    0x0010    Show integers in decimal format
  951.     ios::oct    0x0020    Show integers in octal format
  952.     ios::hex    0x0040    Show integers in hexadecimal format
  953.  
  954.    To guarantee that decimal output is used, you must turn on the bit
  955. ios::dec, and ensure that the remaining 2 bits are turned off. The same
  956. reasoning applies to octal and hex output. But we proved in example
  957. OUTPUT-11 that no bit pertaining to the output base is on by default.
  958. Therefore, which base will be used? The answer is that the compiler will
  959. default to decimal output if none of the 3 base field bits is on. But be
  960. careful! If more than one output base bit happens to be on, then the
  961. output is unpredictable. (Of course, you would never deliberately put
  962. yourself in this situation.). Remember: Once the base has been set, it
  963. stays set for all future integers unless it is subsequently changed.
  964.  
  965.    Recall that the field ios::basefield has been defined for you to
  966. contain all 3 base field bits ORed together, and should be used in the
  967. second parameter of setf to ensure that all 3 bits are turned off before
  968. altering them. So now let's create a program to output the number 65 using
  969. the default base, followed by the base in octal, hexadecimal, and decimal.
  970. (NOTE: a better way in which to write this program will be shown in the
  971. chapter on manipulators.)
  972.  
  973.     // EXAMPLE OUTPUT-21
  974.  
  975.     // HOW TO PRINT IN DECIMAL, OCTAL
  976.     // AND HEXADECIMAL FORMATS
  977.  
  978.     #include <header.h>
  979.  
  980.     int main()
  981.     {
  982.        cout << 65 << '\n' ;
  983.        cout.setf(ios::oct , ios::basefield) ;
  984.        cout << 65 << '\n' ;
  985.        cout.setf(ios::hex , ios::basefield) ;
  986.      cout << 65 << '\n' ;
  987.      cout.setf(ios::dec , ios::basefield) ;
  988.      cout << 65 << '\n' ;
  989.  
  990.        return 0 ;
  991.     }
  992.  
  993. The output of this program, as expected, is:
  994.  
  995.     65
  996.     101
  997.     41
  998.     65
  999.  
  1000. ==========================================================
  1001.  
  1002.    One final point: In a printf() function call, the use of the flag #
  1003. causes the base of an octal or hexadecimal number to appear (0 and 0x,
  1004. respectively). The same effect can be achieved in C++ by setting on the
  1005. bit ios::showbase. Here is example OUTPUT-21 again, but this time the
  1006. base of the octal and hexadecimal numbers is shown. To turn off this
  1007. feature, use the unsetf function.
  1008.  
  1009.     // EXAMPLE OUTPUT-22
  1010.  
  1011.     // HOW TO PRINT IN DECIMAL, OCTAL
  1012.     // AND HEXADECIMAL FORMATS AND SHOW
  1013.     // THE BASE FOR OCTAL AND HEX
  1014.     // NUMBERS
  1015.  
  1016.     #include <header.h>
  1017.  
  1018.     int main()
  1019.     {
  1020.         cout.setf(ios::showbase) ;
  1021.        cout << 65 << '\n' ;
  1022.        cout.setf(ios::oct , ios::basefield) ;
  1023.         cout << 65 << '\n' ;
  1024.        cout.setf(ios::hex , ios::basefield) ;
  1025.        cout << 65 << '\n' ;
  1026.        cout.setf(ios::dec , ios::basefield) ;
  1027.        cout << 65 << '\n' ;
  1028.  
  1029.        return 0 ;
  1030.     }
  1031.  
  1032. The output of this program is:
  1033.  
  1034.     65
  1035.     0101
  1036.     0x41
  1037.     65
  1038.  
  1039. ==========================================================
  1040.  
  1041.    Note that on positive decimal output, a '+' sign is assumed. If you
  1042. want this sign to appear, turn on the bit ios::showpos. (Of course, if
  1043. the number is negative, the '-' sign will always appear.) To turn off this
  1044. feature, use the unsetf() function. In this example the number 65 is
  1045. displayed with a '+' sign.
  1046.  
  1047.     // EXAMPLE OUTPUT-23
  1048.  
  1049.     // HOW TO SHOW THE SIGN OF A POSITIVE
  1050.     // NUMBER
  1051.  
  1052.     #include <header.h>
  1053.  
  1054.     int main()
  1055.     {
  1056.         cout.setf(ios::showpos) ;
  1057.        cout << 65 << '\n' ;
  1058.  
  1059.        return 0 ;
  1060.     }
  1061.  
  1062. The output of this program is:
  1063.  
  1064.     +65
  1065.  
  1066. ==========================================================
  1067.  
  1068.    There is one other option you can employ with hexadecimal numbers. By
  1069. default any hex digit, as well as the 'x' in the base, appears in lower-
  1070. case. The same rule applies to the 'e' when printing in scientific
  1071. notation. If you want to see upper-case, turn on the bit ios::uppercase.
  1072. To revert back to lower-case, use the unsetf() function.
  1073.  
  1074.    This example prints the number 171 in hexadecimal, and shows all hex
  1075. digits in upper-case.
  1076.  
  1077.     // EXAMPLE OUTPUT-24
  1078.  
  1079.     // HOW TO PRINT HEX DIGITS IN
  1080.     // UPPER CASE LETTERS
  1081.  
  1082.     #include <header.h>
  1083.  
  1084.     int main()
  1085.     {
  1086.        cout.setf(ios::uppercase | ios::showbase) ;
  1087.        cout.setf(ios::hex , ios::basefield) ;
  1088.         cout << 171 << '\n' ;
  1089.  
  1090.        return 0 ;
  1091.     }
  1092.  
  1093. The output of this program is:
  1094.  
  1095.     0XAB
  1096.  
  1097. ==========================================================
  1098.  
  1099. Character output
  1100.  
  1101.    Integer output pertains to the display of decimal, octal and
  1102. hexadecimal numbers. The next question is: Can you emulate %c in a
  1103. printf() function call to set the base for character output, i.e., set it
  1104. so that all integral values appear in their character representations?
  1105. Unfortunately, the answer is no. However, the problem only arises when a
  1106. non-character value needs to be displayed in its character form, because
  1107. if you define a character using type char, then it will automatically be
  1108. shown in its character format. Thus, to make a non-char type appear in
  1109. character format, an explicit cast to type char is required.
  1110.  
  1111.    For example, this program prints the letter A five times:
  1112.  
  1113.     // EXAMPLE OUTPUT-31
  1114.  
  1115.     // HOW TO PRINT A CHARACTER AND A
  1116.     // NON-CHARACTER IN CHARACTER
  1117.     // FORMAT.
  1118.  
  1119.     #include <header.h>
  1120.  
  1121.     int main()
  1122.     {
  1123.           // No cast needed here
  1124.           char ch1 = 'A' ;
  1125.           cout << ch1 << '\n' ;
  1126.          char ch2 = 65 ;
  1127.           cout << ch2 << '\n' ;
  1128.  
  1129.           // Cast needed here
  1130.           int ch3 = 65 ;
  1131.           cout << (char)ch3 << '\n' ;
  1132.           int ch4 = 0101 ;
  1133.           cout << (char)ch4 << '\n' ;
  1134.           int ch5 = 0x41 ;
  1135.           cout << (char)ch5 << '\n' ;
  1136.  
  1137.        return 0 ;
  1138.     }
  1139.  
  1140. The output of this program is:
  1141.  
  1142.     A
  1143.     A
  1144.     A
  1145.     A
  1146.     A
  1147.  
  1148. ==========================================================
  1149.  
  1150.    How about the opposite? That is, suppose you want a character to be
  1151. shown in its decimal, octal, and hexadecimal representations. Once again,
  1152. a cast is required, this time to type int. By doing this cast in
  1153. conjunction with the proper base setting, the desired result can be
  1154. obtained. In this example, the character ch is shown in its decimal,
  1155. octal, and hexadecimal representations.
  1156.  
  1157.     // EXAMPLE OUTPUT-32
  1158.  
  1159.     // HOW TO PRINT A CHARACTER AS A
  1160.     // DECIMAL, OCTAL AND HEXADECIMAL
  1161.     // VALUE.
  1162.  
  1163.     #include <header.h>
  1164.  
  1165.     int main()
  1166.     {
  1167.         char ch = 'A' ;
  1168.  
  1169.         cout << (int)ch << '\n' ;
  1170.        cout.setf(ios::oct , ios::basefield) ;
  1171.        cout << (int)ch << '\n' ;
  1172.        cout.setf(ios::hex , ios::basefield) ;
  1173.        cout << (int)ch << '\n' ;
  1174.  
  1175.        return 0 ;
  1176.     }
  1177.  
  1178. The output of this program is:
  1179.  
  1180.     65
  1181.     101
  1182.     41
  1183.  
  1184. ==========================================================
  1185.  
  1186.    There is another way to guarantee that an integral value gets shown in
  1187. its character format. That is with the use of the member function called
  1188. put() (think of the C function putchar()). This function always outputs
  1189. its one argument in character format, regardless of how it was defined.
  1190. This example prints the character A three times.
  1191.  
  1192.     // EXAMPLE OUTPUT-33
  1193.  
  1194.     // HOW TO USE THE MEMBER FUNCTION
  1195.     // put TO OUTPUT A CHARACTER
  1196.  
  1197.     #include <header.h>
  1198.  
  1199.     int main()
  1200.     {
  1201.      char ch1 = 'A' ;
  1202.      int ch2 = 65 ;
  1203.  
  1204.        cout.put(ch1) << '\n' ;
  1205.        cout.put('A') << '\n' ;
  1206.        cout.put(ch2) << '\n' ;
  1207.  
  1208.        return 0 ;
  1209.     }
  1210.  
  1211. ==========================================================
  1212.  
  1213. Setting the field width
  1214.  
  1215.    The field width in C++ works in a similar manner to that of C. If the
  1216. total number of characters needed for output is less than the specified
  1217. width, then the extra spaces will be filled with the current fill
  1218. character. If the number of characters is greater than the specified
  1219. width, then the width is "expanded" to accommodate the entire field. (In C
  1220. the fill character in a printf() function call can only be either a zero
  1221. or a space; in C++ it can be any character you desire. This topic is
  1222. dicussed following width.)
  1223.  
  1224.    If no width is ever specified, then the default value of zero is
  1225. assumed (just as it is in C). To change the field width, use the member
  1226. function width() with one argument: the width value itself. Then the next
  1227. field to be output will use this value.
  1228.  
  1229.    For example, this program prints the number 1 right-justified and
  1230. preceded by 4 blanks, while the number 23 has 3 preceding blanks.
  1231.  
  1232.     // EXAMPLE OUTPUT-41
  1233.  
  1234.     // HOW TO SET THE FIELD WIDTH
  1235.  
  1236.     #include <header.h>
  1237.  
  1238.     int main()
  1239.     {
  1240.        cout.width(5) ;
  1241.        cout << 1 << '\n' ;
  1242.        cout.width(5) ;
  1243.        cout << 23 << '\n' ;
  1244.  
  1245.        return 0 ;
  1246.     }
  1247.  
  1248. The output of this program is:
  1249.  
  1250.          1
  1251.        23
  1252.  
  1253. ==========================================================
  1254.  
  1255.    Something should strike you as odd about this example. Why was it
  1256. necessary to write the line cout.width(5) twice? The answer is that the
  1257. width specification only applies to the next field to be output. To prove
  1258. this statement, let's modify this example slightly and remove the second
  1259. width setting.
  1260.  
  1261.     // EXAMPLE OUTPUT-42
  1262.  
  1263.     // NOTE THAT THE WIDTH SETTING
  1264.     // ONLY APPLIES TO THE NEXT FIELD
  1265.     // TO BE OUTPUT
  1266.  
  1267.     #include <header.h>
  1268.  
  1269.     int main()
  1270.     {
  1271.        cout.width(5) ;
  1272.        cout << 1 << '\n' ;
  1273.         cout << 23  << '\n' ;
  1274.  
  1275.        return 0 ;
  1276.     }
  1277.  
  1278. The output of this program is:
  1279.  
  1280.          1
  1281.     23
  1282.  
  1283. Now the number 23 appears left-justified because the width reverted back
  1284. to its default value of 0.
  1285.  
  1286. ==========================================================
  1287.  
  1288.    In addition to setting the field width, the width() function also
  1289. returns the value of the width just prior to the function call. If you
  1290. wish to return this value and leave it alone, then call the width()
  1291. function with no argument specified.
  1292.  
  1293.    IMPORTANT NOTE: Under the current implementation of Borland C++,
  1294. the field width specification does not apply to character
  1295. fields that are output. This does not mean that the width reverts back to
  1296. zero upon encountering a character field, but instead is applied to the
  1297. next non-character field that is encountered. For example:
  1298.  
  1299. // EXAMPLE OUTPUT-43
  1300.  
  1301. // SHOW THE BUG WITH THE width()
  1302. // FUNCTION
  1303.  
  1304. #include <header.h>
  1305.  
  1306. int main()
  1307. {
  1308.    cout.width(5) ;
  1309.    cout << 'A' << 123 << '\n' ;
  1310.  
  1311.    return 0 ;
  1312. }
  1313.  
  1314. The output of this program is:
  1315.  
  1316.     A  123
  1317.  
  1318. whereas if the width(5) call had been applied to the 'A', the output
  1319. would have been:
  1320.  
  1321.        A123
  1322.  
  1323. ==========================================================
  1324.  
  1325. Specifying the fill character
  1326.  
  1327.    If the total number of characters needed to display a field is less
  1328. than the current field width, the extra output spaces will be filled with
  1329. the current fill character. In a printf() function call, the default fill
  1330. character is a blank, and you only have the option to change it to a zero.
  1331.  
  1332.    In C++, however, you now have the option for any character to serve as
  1333. the fill character. As before, the default is a blank. The member function
  1334. fill() is used to specify a new fill character. Once it is specified, it
  1335. remains as the fill character unless it is subsequently changed. The
  1336. function takes a single argument: the new fill character, and returns the
  1337. previous fill character. As with width(), it may be called with no actual
  1338. argument if you merely want to return the previous fill character.
  1339.  
  1340.    This example outputs the default fill character, changes it to an
  1341. asterisk, and then proves that the current fill character is, indeed, an
  1342. asterisk.
  1343.  
  1344.     // EXAMPLE OUTPUT-51
  1345.  
  1346.     // HOW TO SET THE FILL CHARACTER
  1347.  
  1348.     #include <header.h>
  1349.  
  1350.     int main()
  1351.     {
  1352.        char old_fill = cout.fill('*') ;
  1353.        cout << "Old fill character is "
  1354.                << SINGLE_QUOTE
  1355.                << old_fill
  1356.                << SINGLE_QUOTE
  1357.                << '\n' ;
  1358.  
  1359.          cout << "It was changed to "
  1360.               << SINGLE_QUOTE
  1361.               << cout.fill()
  1362.               << SINGLE_QUOTE
  1363.               << '\n' ;
  1364.  
  1365.        return 0 ;
  1366.     }
  1367.  
  1368. The output of this program is:
  1369.  
  1370.     Old fill character is ' '
  1371.     It was changed to '*'
  1372.  
  1373. ==========================================================
  1374.  
  1375.    Now let's re-run example OUTPUT-41, but this time we'll fill the first
  1376. field with zeroes, and the second with asterisks.
  1377.  
  1378.     // EXAMPLE OUTPUT-52
  1379.  
  1380.     // A COMBINATION OF SETTING THE
  1381.     // FIELD WIDTH AND SPECIFYING
  1382.     // THE FILL CHARACTER
  1383.  
  1384.     #include <header.h>
  1385.  
  1386.     int main()
  1387.     {
  1388.        cout.width(5) ;
  1389.        cout.fill('0') ;
  1390.        cout << 1 << '\n' ;
  1391.        cout.width(5) ;
  1392.        cout.fill('*') ;
  1393.        cout << 23 << '\n' ;
  1394.  
  1395.        return 0 ;
  1396.     }
  1397.  
  1398. The output of this program is:
  1399.  
  1400.     00001
  1401.     ***23
  1402.  
  1403. ==========================================================
  1404.  
  1405. Field justification
  1406.  
  1407.    Whenever a field gets output, and the field width is greater than the
  1408. number of characters needed to display the field, the data is always
  1409. right-justified with the fill character used as padding to the left. (Of
  1410. course, if the field width is less than or equal to the number of
  1411. characters needed, no justification occurs and the fill character is
  1412. ignored.)
  1413.  
  1414.    Recall that there are 3 bits which are used to set the field
  1415. justification:
  1416.  
  1417.   ios::left     0x0002  Left-justification of output
  1418.   ios::right    0x0004  Right-justification of output
  1419.     ios::internal    0x0008    Pad after sign or base indicator
  1420.  
  1421.    If no bit is set in the field x_flags, then the justification defaults
  1422. to right. Once the justification has been set, it remains set unless it is
  1423. subsequently changed. As with setting the base, there is a field called
  1424. ios::adjustfield which has been defined with all 3 justification bits
  1425. turned on. When setting the justification, this field should be used as
  1426. the second argument in the setf() member function call to ensure that the
  1427. other 2 bits are turned off. To set the justification to left, use the
  1428. member function setf() with the bit ios::left, and to change it back to
  1429. right, use the bit ios::right.
  1430.  
  1431.    Here is example OUTPUT-41 again, this time with both fields left-
  1432. justified.
  1433.  
  1434.     // EXAMPLE OUTPUT-61
  1435.  
  1436.     // HOW TO LEFT-JUSTIFY A FIELD
  1437.  
  1438.     #include <header.h>
  1439.  
  1440.     int main()
  1441.     {
  1442.        cout.setf(ios::left , ios::adjustfield) ;
  1443.         cout.width(5) ;
  1444.         cout.fill('0') ;
  1445.        cout << 1 << '\n' ;
  1446.         cout.width(5) ;
  1447.        cout.fill('*') ;
  1448.         cout << 23 << '\n' ;
  1449.  
  1450.        return 0 ;
  1451.     }
  1452.  
  1453. The output of this program is:
  1454.  
  1455.     10000
  1456.     23***
  1457.  
  1458. ==========================================================
  1459.  
  1460.    The justification resulting from the ios::internal bit means that
  1461. padding with the fill character, if any, will occur after the base of the
  1462. number has been shown (for octal and hexadecimal numbers) and before the
  1463. number itself. In the case of decimal numbers, the padding will occur
  1464. after the sign ('+' or '-') and before the number itself. That is, instead
  1465. of padding occurring on the left or on the right, it occurs "in the
  1466. middle".
  1467.  
  1468.    In this example, the base is shown, the fill character is set to '=',
  1469. the internal bit is set on, the field width is set to 10, hexadecimal
  1470. output is requested, and the number 65 is printed. Then the same number is
  1471. printed again, but with left justification.
  1472.  
  1473. ==========================================================
  1474.  
  1475.     // EXAMPLE OUTPUT-62
  1476.  
  1477.     // HOW TO DO INTERNAL JUSTIFICATION
  1478.  
  1479.     #include <header.h>
  1480.  
  1481.     int main()
  1482.     {
  1483.         cout.setf(ios::showbase) ;
  1484.         cout.fill('=') ;
  1485.        cout.setf(ios::internal , ios::adjustfield) ;
  1486.         cout.width(10) ;
  1487.        cout.setf(ios::hex , ios::basefield) ;
  1488.        cout << 65 << '\n' ;
  1489.         cout.setf(ios::left , ios::adjustfield) ;
  1490.        cout.width(10) ;
  1491.         cout << 65 << '\n' ;
  1492.  
  1493.        return 0 ;
  1494.     }
  1495.  
  1496. The output of this program is:
  1497.  
  1498.     0x======41
  1499.     0x41======
  1500.  
  1501. ==========================================================
  1502.  
  1503. Floating Point Output
  1504.  
  1505.    Floating point numbers are output in C++ just like any other type of
  1506. number. However, the formatting is certainly different, and default values
  1507. are not the same as you would get from using a printf() function call.
  1508.  
  1509.    In this example some floating point constants are output.
  1510.  
  1511.     // EXAMPLE OUTPUT-71
  1512.  
  1513.     // DISPLAY SOME FLOATING POINTS
  1514.     // CONSTANTS WITHOUT ANY FORMATTING
  1515.  
  1516.     #include <header.h>
  1517.  
  1518.     int main()
  1519.     {
  1520.      cout << 1.2300 << '\n' ;
  1521.      cout << 4.00 << '\n' ;
  1522.      cout << 5.678E2 << '\n' ;
  1523.      cout << 0.0 << '\n' ;
  1524.  
  1525.        return 0 ;
  1526.     }
  1527.  
  1528. The output of this program is:
  1529.  
  1530.     1.23
  1531.     4
  1532.     567.8
  1533.     0
  1534.  
  1535.    For the first constant, note that the 2 trailing zeroes were not
  1536. printed. This is certainly different from printf() in which the default
  1537. is to show 6 positions after the decimal point. In the second case, not
  1538. only do the trailing zeroes not show, but even the decimal point does not
  1539. appear. In the third case, the number prints in fixed point notation
  1540. despite being keyed in scientific notation. In the final case, at least
  1541. one significant digit will always appear.
  1542.  
  1543.    Thus, we can infer that by default, all trailing zeroes, even the
  1544. decimal point, will be suppressed. If you really want to emulate how the
  1545. printf() function works, you need to turn on the ios::showpoint bit. To
  1546. revert back to the default value, use the function unsetf() to turn it
  1547. off. Here is the same example with this bit now on in the field x_flags.
  1548.  
  1549.     // EXAMPLE OUTPUT-72
  1550.  
  1551.     // HOW TO EMULATE printf()
  1552.  
  1553.     #include <header.h>
  1554.  
  1555.     int main()
  1556.     {
  1557.         cout.setf(ios::showpoint) ;
  1558.         cout << 1.2300 << '\n' ;
  1559.        cout << 4.00 << '\n' ;
  1560.        cout << 5.678E2 << '\n' ;
  1561.        cout << 0.0 << '\n' ;
  1562.  
  1563.        return 0 ;
  1564.     }
  1565.  
  1566. The output of this program is:
  1567.  
  1568.     1.230000
  1569.     4.000000
  1570.     567.800000
  1571.     0.000000
  1572.  
  1573. ==========================================================
  1574.  
  1575.    The next step is to override the default of 6 decimal positions. To do
  1576. this, use the member function precision() in which the one argument is
  1577. the number of decimal positions to be shown. This function also returns
  1578. the previous value of the precision. If it is called without an argument,
  1579. it merely returns the current value of the precision and does not alter
  1580. it. The default precision is 0.
  1581.  
  1582.    Here is the same example with the precision now set to 1.
  1583.  
  1584.     // EXAMPLE OUTPUT-73
  1585.  
  1586.     // HOW TO EMULATE printf() AND SET
  1587.     // THE PRECISION
  1588.  
  1589.     #include <header.h>
  1590.  
  1591.     int main()
  1592.     {
  1593.      cout.setf(ios::showpoint) ;
  1594.         cout.precision(1) ;
  1595.        cout << 1.2300 << '\n' ;
  1596.      cout << 4.00 << '\n' ;
  1597.         cout << 5.678E2 << '\n' ;
  1598.      cout << 0.0 << '\n' ;
  1599.  
  1600.        return 0 ;
  1601.     }
  1602.  
  1603. The output of this program is:
  1604.  
  1605.     1.2
  1606.     4.0
  1607.     5.7e+02
  1608.     0.0
  1609.  
  1610. ==========================================================
  1611.  
  1612.    Note that the third answer is displayed in scientific notation. To
  1613. guarantee that all output is shown in either fixed decimal or scientific
  1614. notation, recall that the following bits are pre-defined in the class
  1615. ios:
  1616.  
  1617.   ios::scientific 0x0800  Use exponential notation on floating point numbers
  1618.   ios::fixed      0x1000  Use fixed decimal output on floating point numbers
  1619.  
  1620.    If neither bit is turned on, then the compiler emulates the %g
  1621. conversion specification in a printf() function call. Also recall that
  1622. there is a constant called ios:floatfield that is the value of these two
  1623. bits ORed together, and may be used as the second argument in a setf()
  1624. function call.
  1625.  
  1626.     // EXAMPLE OUTPUT-74
  1627.  
  1628.     // HOW TO EMULATE printf(), SET
  1629.     // THE PRECISION, AND GUARANTEE
  1630.     // FIXED OR SCIENTIFIC OUTPUT
  1631.  
  1632.     #include <header.h>
  1633.  
  1634.     int main()
  1635.     {
  1636.      cout.setf(ios::showpoint) ;
  1637.        cout.precision(2) ;
  1638.  
  1639.      // Guarantee fixed decimal
  1640.         cout.setf(ios::fixed , ios::floatfield) ;
  1641.        cout << 1.2300 << '\n' ;
  1642.        cout << 4.00 << '\n' ;
  1643.         cout << 5.678E2  << '\n' ;
  1644.        cout << 0.0 << '\n' ;
  1645.  
  1646.      // Guarantee scientific
  1647.         cout.setf(ios::scientific , ios::floatfield) ;
  1648.         cout << 1.2300 << '\n' ;
  1649.         cout << 4.00  << '\n' ;
  1650.         cout << 5.678E2<< '\n' ;
  1651.         cout << 0.0 << '\n' ;
  1652.  
  1653.        return 0 ;
  1654.     }
  1655.  
  1656. The output of this program is:
  1657.  
  1658.     1.23
  1659.     4.00
  1660.     567.80
  1661.     0.00
  1662.     1.23e+00
  1663.     4.00e+00
  1664.     5.68e+02
  1665.     0.00e+00
  1666.  
  1667. ==========================================================
  1668.  
  1669. Printing addresses
  1670.  
  1671.    The address of a variable (or instance of a class) can be generated by
  1672. using the address operator (&). Because the address operator can be
  1673. applied to a wide variety of types (both built-in and user-defined), the
  1674. type of argument can theoretically be "pointer to int" or "pointer to
  1675. float" or even "pointer to my class type". To accommodate all of these
  1676. various types, the class ostream contains an overloaded function
  1677. operator<< to handle all such argument types. This function is
  1678. prototyped to accept an argument of type void* which, according to the
  1679. rules of argument matching, is acceptable to the compiler as a "match".
  1680.  
  1681.    In Borland C++, this address is always shown in 32-bit (4
  1682. byte) hexadecimal form, even though the default output base is decimal.
  1683.  
  1684. ==========================================================
  1685.  
  1686.     // EXAMPLE OUTPUT-81
  1687.  
  1688.     // HOW TO PRINT AN ADDRESS
  1689.  
  1690.     #include <header.h>
  1691.  
  1692.     int main()
  1693.     {
  1694.      int number ;
  1695.  
  1696.      cout << "Address of number as a\n"
  1697.           << "  32-bit hex is "
  1698.           << &number
  1699.           << '\n' ;
  1700.  
  1701.        return 0 ;
  1702.     }
  1703.  
  1704. The output of this program is:
  1705.  
  1706.     Address of a number as a
  1707.        32-bit hex is 0x204cfff4
  1708.  
  1709. ==========================================================
  1710.  
  1711.    Since the 8086 microprocessor chip uses only 16-bit addressing, the
  1712. highest address possible is 65,535. This obviously is insufficient to
  1713. handle the addresses on a computer with 1MB of RAM. What is really needed
  1714. is a 20-bit address. Therefore, the address is divided between 2 hardware
  1715. registers, the first called the segment register, and the second called
  1716. the offset register. A segment is a 64K region of RAM that starts on an
  1717. even multiple of 16 bytes. The location of any byte within a segment is
  1718. determined by the offset. Thus, the physical 20-bit address of any
  1719. specific byte within the computer is determined by shifting the segment
  1720. address left 4 bits (1 hex digit, or a value of 16) and adding the offset
  1721. value. The resulting address is usually shown in "segment:offset" form,
  1722. just like the %p conversion specification in a printf() function call.
  1723.  
  1724.    Here is a program that prints an address in "segment:offset" form. The
  1725. header file dos.h is needed here, and included in the file header.h.
  1726.  
  1727.     // EXAMPLE OUTPUT-82
  1728.  
  1729.     // HOW TO PRINT AN ADDRESS IN
  1730.     // SEGMENT:OFFSET FORM
  1731.  
  1732.     #include <header.h>
  1733.  
  1734.     int main()
  1735.     {
  1736.      int number ;
  1737.  
  1738.      cout << "Address of number in\n"
  1739.           << "  segment:offset form "
  1740.           << "is\n  "
  1741.           << FP_SEG(&number)
  1742.           << ":"
  1743.           << FP_OFF(&number)
  1744.           << '\n' ;
  1745.  
  1746.        return 0 ;
  1747.     }
  1748.  
  1749. The output of this program is:
  1750.  
  1751.     Address of number in
  1752.       segment:offset form is
  1753.       7846:65524
  1754.  
  1755. ==========================================================
  1756.  
  1757.    Also in the file header.h is a function called ADDRESS() that does
  1758. the same thing. Caution: do not call this function more than once in a
  1759. single statement using cout.
  1760.  
  1761.     // EXAMPLE OUTPUT-83
  1762.  
  1763.     // HOW TO PRINT AN ADDRESS
  1764.     // USING A FUNCTION
  1765.  
  1766.     #include <header.h>
  1767.  
  1768.     int main()
  1769.     {
  1770.      int number ;
  1771.  
  1772.      cout << "Address of number in\n"
  1773.           << "  segment:offset form "
  1774.           << "is\n  "
  1775.           << ADDRESS(&number)
  1776.           << '\n' ;
  1777.  
  1778.        return 0 ;
  1779.     }
  1780.  
  1781. The output of this program is:
  1782.  
  1783.     Address of number in
  1784.       segment:offset form is
  1785.       7846:65524
  1786.  
  1787. ==========================================================
  1788.  
  1789.    When dealing with a string, a problem arises. It's the same problem
  1790. that occurred in C in a program fragment such as:
  1791.  
  1792.     char* ptr = "ABC" ;
  1793.   printf("%s" , ptr) ;
  1794.  
  1795. No doubt the user will see ABC as the output. The problem is how to print
  1796. the address contained within the pointer variable ptr. The solution in C
  1797. is to provide a different conversion specification, namely %p.
  1798.  
  1799.    In C++ this program fragment:
  1800.  
  1801.     char* ptr = "ABC" ;
  1802.     cout << ptr ;
  1803.  
  1804. would also output ABC because the argument ptr is of type char* which
  1805. matches exactly an overloaded operator<< that accepts an argument of
  1806. type char*. To emulate the %p in C++, you must override the built-in type
  1807. of char* with the type void* so that the operator<< function that
  1808. outputs an address will be called instead. The ADDRESS manipulator
  1809. automatically casts every address it sees into void*.
  1810.  
  1811.     // EXAMPLE OUTPUT-84
  1812.  
  1813.     // HOW TO PRINT THE ADDRESS OF
  1814.     // A STRING
  1815.  
  1816.     #include <header.h>
  1817.  
  1818.     int main()
  1819.     {
  1820.      char* ptr = "ABC" ;
  1821.  
  1822.      cout << "The string itself is "
  1823.           << ptr
  1824.           << '\n' ;
  1825.  
  1826.      cout << "The address of the "
  1827.           << "string is "
  1828.           << ADDRESS(ptr)
  1829.           << '\n' ;
  1830.  
  1831.        return 0 ;
  1832.     }
  1833.  
  1834. The output of this program is:
  1835.  
  1836.     The string itself is ABC
  1837.     The address of the string is 7848:604
  1838.  
  1839. ==========================================================
  1840.  
  1841. Binary output
  1842.  
  1843.    It's possible to take any internal representation of a C++ type and
  1844. output it as though it were just an array of characters. For a type such
  1845. as float, this will produce meaningless output, but it may be useful for
  1846. integers. To do this, the member function write() must be used. This
  1847. function takes 2 arguments: The first is the address of the data to be
  1848. output, and the second is the number of bytes to be shown. Note that in
  1849. the case of a string, the null byte is treated just like any other byte.
  1850.  
  1851.    Because the function write() is declared to accept an argument of type
  1852. char*, if the item you wish to print is not of this type, then the
  1853. address must be generated using the address operator, and then cast to
  1854. type char*.
  1855.  
  1856. ==========================================================
  1857.  
  1858.     // EXAMPLE OUTPUT-91
  1859.  
  1860.     // HOW TO DISPLAY THE BINARY REPRE-
  1861.     // SENTATION OF A NUMBER
  1862.  
  1863.     #include <header.h>
  1864.  
  1865.     int main()
  1866.     {
  1867.        long number = 0x414243 ;
  1868.  
  1869.        cout.write((char*)&number , sizeof(number)) ;
  1870.        cout << '\n' ;
  1871.  
  1872.        return 0 ;
  1873.     }
  1874.  
  1875. Note that the output of this program is CBA, because the address of a
  1876. long refers to the low-order byte.
  1877.  
  1878. ==========================================================
  1879.  
  1880. Incore output
  1881.  
  1882.    Incore output refers to how you can send output to an in-memory buffer
  1883. of type char* instead of to the screen.
  1884.  
  1885.    In C this is done by using the function sprintf(), where the first
  1886. argument specifies the address of the buffer area where the data is to be
  1887. stored. For example:
  1888.  
  1889.     // EXAMPLE OUTPUT-95
  1890.  
  1891.     // HOW TO DO INCORE OUTPUT USING C
  1892.  
  1893.     #include <header.h>
  1894.  
  1895.     int main(void)
  1896.     {
  1897.      int number = 123 ;
  1898.      char buffer[80] ;
  1899.  
  1900.      sprintf(buffer,"number is %d", number) ;
  1901.      printf ("buffer contains: "
  1902.              "%c%s%c\n" ,
  1903.              DOUBLE_QUOTE ,
  1904.              buffer ,
  1905.              DOUBLE_QUOTE) ;
  1906.  
  1907.      return 0 ;
  1908.     }
  1909.  
  1910. The output of this program is:
  1911.  
  1912.     buffer contains: "number is 123"
  1913.  
  1914. ==========================================================
  1915.  
  1916.    In order to accomplish the same result in C++ you must first include
  1917. the header file strstream.h (this is already done in the file
  1918. header.h). This file contains the declaration of the class ostrstream,
  1919. which you then use to create some instance. At the time of creation, you
  1920. must provide two arguments: (1) the address of the buffer where the data
  1921. is to be written, and (2) the maximum size of this buffer (which normally
  1922. is the sizeof the buffer). For example,
  1923.  
  1924.     char buffer [80] ;
  1925.     ostrstream output(buffer , sizeof buffer) ;
  1926.  
  1927.    After this has been done, the instance output is used where you would
  1928. normally use cout. All of the data is thus sent to the buffer area. If
  1929. you subsequently want to send this buffer area to the screen, don't
  1930. forget to append a null byte to make the buffer a legitimate string
  1931. object. If you subsequently wish to place more output into this buffer
  1932. area starting back at character position 0, you must use the (inherited)
  1933. member function seekp() with an argument of 0.
  1934.  
  1935.     // EXAMPLE OUTPUT-96
  1936.  
  1937.     // HOW TO DO INCORE OUTPUT IN C++
  1938.  
  1939.     #include <header.h>
  1940.  
  1941.     int main()
  1942.     {
  1943.      int number = 123 ;
  1944.      char buffer[80] ;
  1945.  
  1946.      ostrstream output(buffer , sizeof buffer);
  1947.  
  1948.      output << "number is "
  1949.             << number
  1950.             << '\0' ;
  1951.      cout << DOUBLE_QUOTE
  1952.           << buffer
  1953.           << DOUBLE_QUOTE
  1954.           << '\n' ;
  1955.  
  1956.      output.seekp(0) ;
  1957.      output << "A new buffer stream "
  1958.             << "of characters"
  1959.             << '\0' ;
  1960.      cout << DOUBLE_QUOTE
  1961.           << buffer
  1962.           << DOUBLE_QUOTE
  1963.           << '\n' ;
  1964.  
  1965.      return 0 ;
  1966.     }
  1967.  
  1968. The output of this program is:
  1969.  
  1970.     "number is 123"
  1971.     "A new buffer stream of characters"
  1972.  
  1973. ==============================================================================
  1974. ==============================================================================
  1975.  
  1976.                               CHAPTER 3 -- Input
  1977.  
  1978. Introduction
  1979.  
  1980.    In addition to being able to use classes to control output, C++ stream
  1981. I/O classes also handle all input. Just as output consists of a stream of
  1982. characters being sent to some device, input consists of characters coming
  1983. in from some device and being translated into their proper defined type.
  1984. In other words, the characters '1', '2' and '3' could be the string "123"
  1985. or the integer 123, depending upon the type of the receiving field.
  1986. Unlike output, the realm of possibilities for ╥formatting╙ simply does
  1987. not exist when inputting data.
  1988.  
  1989.    The class istream is derived from the class ios, and it controls the
  1990. input handling functions. The global instance that is defined for you is
  1991. called cin, and is defined as:
  1992.  
  1993.         istream cin ;
  1994.  
  1995.    In addition to data members, the class istream contains functions to
  1996. format the stream of characters received from some input device, and
  1997. present them to you in the manner in which you expect to receive them.
  1998. The function you will use the most often is called the extraction
  1999. operator, and it is written as:
  2000.  
  2001.         operator>>
  2002.  
  2003.    The argument to this function is the variable name that you wish to
  2004. contain the input data. The name ╥extraction╙ comes from the fact that
  2005. you are ╥extracting╙ (taking) data from the input stream.
  2006.  
  2007.    For example, to input an integer, you would code:
  2008.  
  2009.         int number ;
  2010.         cin.operator>>(number) ;
  2011.  
  2012.    As with the insertion operator, this code can be replaced with the
  2013. simpler form:
  2014.  
  2015.         int number ;
  2016.         cin >> number ;
  2017.  
  2018.    Note that the type of the input variable determines how the characters
  2019. from the input stream are to be stored.
  2020.  
  2021.    For example, this program inputs a number, character and float, and
  2022. then echoes them back.
  2023.  
  2024.     // EXAMPLE INPUT-01
  2025.  
  2026.     // HOW TO INPUT SOME SIMPLE TYPES
  2027.  
  2028.     #include <header.h>
  2029.  
  2030.     int main()
  2031.     {
  2032.      int number ;
  2033.      cout << "Enter a number: " ;
  2034.      cin >> number ;
  2035.        cout << "You entered: "
  2036.           << number
  2037.           << '\n' ;
  2038.  
  2039.      char ch ;
  2040.      cout << "Enter a character: " ;
  2041.      cin >> ch ;
  2042.      cout << "You entered: "
  2043.           << ch
  2044.           << '\n' ;
  2045.  
  2046.      float fl ;
  2047.      cout << "Enter a float: " ;
  2048.      cin >> fl ;
  2049.      cout << "You entered: "
  2050.           << fl
  2051.           << '\n' ;
  2052.  
  2053.        return 0 ;
  2054.     }
  2055.  
  2056. ==========================================================
  2057.  
  2058.    The extraction operators, like the insertion operators, can be chained
  2059. together.
  2060.  
  2061.     // EXAMPLE INPUT-02
  2062.  
  2063.     // EXTRACTION OPERATORS CAN BE
  2064.     // CHAINED TOGETHER
  2065.  
  2066.     #include <header.h>
  2067.  
  2068.     int main()
  2069.     {
  2070.      int number1 , number2 ;
  2071.      cout << "Enter 2 numbers: " ;
  2072.      cin >> number1 >> number2 ;
  2073.      cout << "You entered: "
  2074.           << number1
  2075.           << " and "
  2076.           << number2
  2077.           << '\n' ;
  2078.  
  2079.        return 0 ;
  2080.     }
  2081.  
  2082. ==========================================================
  2083.  
  2084. Integer input
  2085.  
  2086.    Recall from the discussion on output that the base setting for integer
  2087. output is, by default, decimal. This setting can, of course, be changed
  2088. by using the setf() function. In a similar manner, the default base
  2089. setting for integer input is decimal. This means that for a variable
  2090. defined as either int or long, only valid integer data is acceptable. An
  2091. attempt to violate this rule will cause an error condition to occur. For
  2092. example, entering A12 for an integer value will cause an error. However,
  2093. entering 12A will cause the number 12 to be stored into the integer, and
  2094. the letter A to remain in the input stream, so that this is not
  2095. necessarily an error condition; it depends on what you do next.
  2096.  
  2097.    Even though the default input base setting is decimal, it is still
  2098. possible to override this default if you wish to input either an octal or
  2099. hexadecimal number. This can be done by explicitly keying the base of
  2100. these numbers, i.e., 0 for octal and 0x (or 0X) for hex. To test this, in
  2101. example INPUT-02 enter the numbers 012 and 0xA. Then the output is: You
  2102. entered: 10 and 10.
  2103.  
  2104.    However, note what happens when the input base setting is explicitly
  2105. set to decimal via a setf() function call (or via a manipulator). In this
  2106. case only decimal input is allowed. Here is example INPUT-02 again, but
  2107. with the base setting explicitly specified. If you enter the numbers 012
  2108. and 0xA, then the output is: You entered: 12 and 0 (the xA remains in
  2109. the buffer).
  2110.  
  2111.     // EXAMPLE INPUT-03
  2112.  
  2113.     // EXPLICITLY GIVE THE INPUT
  2114.     // BASE SETTING
  2115.  
  2116.     #include <header.h>
  2117.  
  2118.     int main()
  2119.     {
  2120.        cin.setf(ios::dec , ios::basefield) ;
  2121.      int number1 , number2 ;
  2122.      cout << "Enter 2 numbers: " ;
  2123.      cin >> number1 >> number2 ;
  2124.      cout << "You entered: "
  2125.           << number1
  2126.           << " and "
  2127.           << number2
  2128.           << '\n' ;
  2129.  
  2130.        return 0 ;
  2131.     }
  2132.  
  2133. ==========================================================
  2134.  
  2135.    It is possible to input octal and hex numbers without having to go to
  2136. the trouble of explicitly keying their respective bases. This can be done
  2137. by changing the base of the input stream from its default setting of
  2138. decimal to either octal or hexadecimal. Essentially, this is how the %o
  2139. and %x conversion specifications in a scanf() function call can be
  2140. emulated.
  2141.  
  2142.    For example, this program prompts the user for numbers in decimal,
  2143. octal, and hexadecimal formats, then echoes each number back. Note that
  2144. the output is always in decimal because the setting of the output base
  2145. has not been affected. In other words, the base setting is stored
  2146. separately for each stream. Obviously, if an illegal input value is
  2147. entered, the value will not be stored. If you enter the number 65 for all
  2148. three prompts, the first is taken as decimal, the second as octal, and
  2149. the third as hex.
  2150.  
  2151.     // EXAMPLE INPUT-04
  2152.  
  2153.     // INTEGERS CAN BE INPUT IN ANY OF
  2154.     // 3 DIFFERENT BASES
  2155.  
  2156.     #include <header.h>
  2157.  
  2158.     int main()
  2159.     {
  2160.      int number ;
  2161.  
  2162.      cout << "Enter a decimal number: " ;
  2163.      cin >> number ;
  2164.      cout << "You entered: "
  2165.           << number
  2166.           << '\n' ;
  2167.  
  2168.      cout << "Enter an octal number: " ;
  2169.        cin.setf(ios::oct , ios::basefield) ;
  2170.      cin >> number ;
  2171.      cout << "You entered: "
  2172.           << number
  2173.           << '\n' ;
  2174.  
  2175.      cout << "Enter a hex number: " ;
  2176.        cin.setf(ios::hex , ios::basefield) ;
  2177.      cin >> number ;
  2178.      cout << "You entered: "
  2179.           << number
  2180.           << '\n' ;
  2181.  
  2182.        return 0 ;
  2183.     }
  2184.  
  2185. The output of this program is:
  2186.  
  2187.     65
  2188.     53
  2189.     101
  2190.  
  2191. ==========================================================
  2192.  
  2193. Character input
  2194.  
  2195.    The simplest way to read in a character is to use the extraction
  2196. operator >>.Leading whitespace characters are bypassed, and the first
  2197. non-whitespace character is fetched. Also, as you would expect, a
  2198. reference to the invoking instance is returned, thereby allowing the
  2199. input operations to be chained together. In this example, enter 2 non-
  2200. whitespace characters, and intersperse them with lots of blanks and tabs.
  2201. Then press <RETURN>. Regardless of the whitespace that you may have
  2202. entered, what will be stored are the 2 non-whitespace characters.
  2203.  
  2204.     // EXAMPLE INPUT-11
  2205.  
  2206.     // DEMONSTRATE HOW TO READ IN A
  2207.     // CHARACTER AND BYPASS LEADING
  2208.     // WHITESPACE
  2209.  
  2210.     #include <header.h>
  2211.  
  2212.     int main()
  2213.     {
  2214.      cout << "Enter 2 characters: " ;
  2215.      char ch1 , ch2 ;
  2216.      cin >> ch1 >> ch2 ;
  2217.      cout << "You entered: "
  2218.           << SINGLE_QUOTE
  2219.           << ch1
  2220.           << SINGLE_QUOTE
  2221.           << " and "
  2222.           << SINGLE_QUOTE
  2223.           << ch2
  2224.           << SINGLE_QUOTE
  2225.           << '\n' ;
  2226.  
  2227.        return 0 ;
  2228.     }
  2229.  
  2230. ==========================================================
  2231.  
  2232.    If you want to consider whitespace characters (including '\n') as
  2233. being just as ╥good╙ as all other characters, then you may turn off the
  2234. bit ios::skipws using the instance cin (not cout). Here is example
  2235. INPUT-11 again, but now the program will store the first 2 characters
  2236. entered.
  2237.  
  2238.     // EXAMPLE INPUT-12
  2239.  
  2240.     // NOW TURN OFF THE BIT ios::skipws
  2241.     // SO THAT ALL CHARACTERS ARE CON-
  2242.     // SIDERED EQUAL
  2243.  
  2244.     #include <header.h>
  2245.  
  2246.     int main()
  2247.     {
  2248.        cin.unsetf(ios::skipws) ;
  2249.      cout << "Enter 2 characters: " ;
  2250.      char ch1 , ch2 ;
  2251.      cin >> ch1 >> ch2 ;
  2252.      cout << "You entered: "
  2253.           << SINGLE_QUOTE
  2254.           << ch1
  2255.           << SINGLE_QUOTE
  2256.           << " and "
  2257.           << SINGLE_QUOTE
  2258.           << ch2
  2259.           << SINGLE_QUOTE
  2260.           << '\n' ;
  2261.  
  2262.        return 0 ;
  2263.     }
  2264.  
  2265. ==========================================================
  2266.  
  2267.    Another method to read characters is provided by the member function
  2268. get(). The previous example can be emulated by using this function. It
  2269. takes a single argument ╤ the character itself, and returns a reference
  2270. to the invoking instance so that the function calls can be chained
  2271. together. The difference between the extraction operator >> and get() is
  2272. that get() does not use the format flags, so by default it does not
  2273. bypass leading whitespace. In this example, enter the same data that you
  2274. used in example INPUT-12.
  2275.  
  2276.     // EXAMPLE INPUT-13
  2277.  
  2278.     // THE MEMBER FUNCTION get()
  2279.     // WITH AN ARGUMENT
  2280.  
  2281.     #include <header.h>
  2282.  
  2283.     int main()
  2284.     {
  2285.      cout << "Enter 2 characters: " ;
  2286.      char ch1 , ch2 ;
  2287.      cin.get(ch1).get(ch2) ;
  2288.      cout << "You entered: "
  2289.           << SINGLE_QUOTE
  2290.           << ch1
  2291.           << SINGLE_QUOTE
  2292.           << " and "
  2293.           << SINGLE_QUOTE
  2294.           << ch2
  2295.           << SINGLE_QUOTE
  2296.           << '\n' ;
  2297.  
  2298.        return 0 ;
  2299.     }
  2300.  
  2301. ==========================================================
  2302.  
  2303.    The get() function has also been overloaded so that it can take no
  2304. input argument (just like getchar() in C). In this form it returns a
  2305. value of type int, which represents the character just read, or the EOF
  2306. constant if either (a) end-of-file was detected, or (b) no character
  2307. could be read.
  2308.  
  2309.    In this example get() is used to read in a character, after which a
  2310. check for end-of-file is made. Because the variable ch must be defined as
  2311. type int, don't forget the cast in order to display it as a character.
  2312.  
  2313.     // EXAMPLE INPUT-14
  2314.  
  2315.     // DEMONSTRATE HOW TO READ IN A
  2316.     // CHARACTER USING getch() WITH NO
  2317.     // ARGUMENT
  2318.  
  2319.     #include <header.h>
  2320.  
  2321.     int main()
  2322.     {
  2323.        cout << "Enter a character: " ;
  2324.         int ch = cin.get() ;
  2325.        if (ch != EOF)
  2326.              cout << "You entered: "
  2327.                   << SINGLE_QUOTE
  2328.                   << (char)ch
  2329.                   << SINGLE_QUOTE
  2330.                   << '\n' ;
  2331.      else
  2332.           cout << "End-of-file\n" ;
  2333.  
  2334.        return 0 ;
  2335.     }
  2336.  
  2337. ==========================================================
  2338.  
  2339. String input
  2340.  
  2341.    As with character input, strings may be entered using the extraction
  2342. operator or the overloaded member function get(). With the extraction
  2343. operator, leading whitespace is bypassed, and the first whitespace
  2344. encountered terminates the input. This acts just like the function
  2345. scanf().
  2346.  
  2347.     // EXAMPLE INPUT-21
  2348.  
  2349.     // DEMONSTRATE HOW TO READ IN A
  2350.     // STRING AND BYPASS WHITESPACE
  2351.     // TOTALLY (LOOKS LIKE scanf())
  2352.  
  2353.     #include <header.h>
  2354.  
  2355.     const int length = 100 ;
  2356.  
  2357.     int main()
  2358.     {
  2359.      char string [length] ;
  2360.  
  2361.      cout << "Enter a string: " ;
  2362.      cin >> string ;
  2363.      cout << "Your string: "
  2364.           << DOUBLE_QUOTE
  2365.           << string
  2366.           << DOUBLE_QUOTE
  2367.           << '\n' ;
  2368.  
  2369.        return 0 ;
  2370.     }
  2371.  
  2372. ==========================================================
  2373.  
  2374.    But just like scanf(), you could have a program hang or crash if the
  2375. operator enters more characters than can safely be accommodated by the
  2376. string array. In other words, run this program and enter more than 10
  2377. characters.
  2378.  
  2379.     // EXAMPLE INPUT-22
  2380.  
  2381.     // IT'S POSSIBLE TO OVERFLOW AN
  2382.     // ARRAY WHEN INPUTTING A STRING
  2383.  
  2384.     #include <header.h>
  2385.  
  2386.     const int max = 10 ;
  2387.  
  2388.     int main()
  2389.     {
  2390.      char string[max] ;
  2391.  
  2392.      cout << "Enter a string: " ;
  2393.      cin >> string ;
  2394.      cout << "You entered: "
  2395.           << DOUBLE_QUOTE
  2396.           << string
  2397.           << DOUBLE_QUOTE
  2398.           << '\n' ;
  2399.  
  2400.        return 0 ;
  2401.     }
  2402.  
  2403. ==========================================================
  2404.  
  2405.    If it didn't bomb, consider yourself lucky. To guard against this
  2406. disaster, you may set the width of the input stream to physically limit
  2407. the number of characters that will be stored. This is done by using the
  2408. member function width() in the class istream. The result is that only
  2409. the number of characters (less 1) specified by the argument to width()
  2410. will be extracted from the input stream; the remaining characters are
  2411. left alone. Run this program and enter the letters 'A' through 'M'. Note
  2412. that only the letters 'A' through 'I' got stored into the string. (The
  2413. last byte is always reserved for the null character.)
  2414.  
  2415.     // EXAMPLE INPUT-23
  2416.  
  2417.     // HOW TO AVOID OVERFLOWING AN
  2418.     // ARRAY WHEN INPUTTING A STRING
  2419.     // WITH THE EXTRACTION OPERATOR
  2420.  
  2421.     #include <header.h>
  2422.  
  2423.     const int max = 10 ;
  2424.  
  2425.     int main()
  2426.     {
  2427.      char string[max] ;
  2428.  
  2429.      cout << "Enter a string: " ;
  2430.        cin.width(max) ;
  2431.      cin >> string ;
  2432.      cout << "You entered: "
  2433.           << DOUBLE_QUOTE
  2434.           << string
  2435.           << DOUBLE_QUOTE
  2436.           << '\n' ;
  2437.  
  2438.        return 0 ;
  2439.     }
  2440.  
  2441. ==========================================================
  2442.  
  2443.    Caution: Just like the width() function used for output, the input
  2444. width() function only applies to the next item to be input.
  2445.  
  2446.    Another way to read in strings is to use the member function get()
  2447. with 3 arguments. Note the similarity to the C function fgets(). The
  2448. first argument is the address of the string area, the second is the
  2449. maximum number of characters (less 1) that can be read in, and the third
  2450. specifies the terminating character (the one that will stop the transfer
  2451. of characters from the buffer into the string array). This third argument
  2452. defaults to the value '\n', which is the <RETURN> key. Note, however,
  2453. that if it is changed to some other character, then the <RETURN> key
  2454. must still be pressed for the input action to cease.  Both leading
  2455. whitespace and embedded whitespace are retained as part of the string
  2456. value.
  2457.  
  2458.     // EXAMPLE INPUT-24
  2459.  
  2460.     // DEMONSTRATE HOW TO READ IN A
  2461.     // STRING AND RETAIN WHITESPACE,
  2462.     // BOTH LEADING AND EMBEDDED
  2463.  
  2464.     #include <header.h>
  2465.  
  2466.     const int length = 100 ;
  2467.  
  2468.     int main()
  2469.     {
  2470.      char string [length] ;
  2471.  
  2472.        cout << "Enter a string: " ;
  2473.      cin.get(string , length) ;
  2474.      cout << "Your string: "
  2475.           << DOUBLE_QUOTE
  2476.           << string
  2477.           << DOUBLE_QUOTE
  2478.           << '\n' ;
  2479.  
  2480.        return 0 ;
  2481.     }
  2482.  
  2483. ==========================================================
  2484.  
  2485.    A slight variation on the function get() taking 3 arguments is the
  2486. function getline(). The only difference is that getline() extracts the
  2487. newline character ('\n') from the input buffer, whereas get() leaves it
  2488. alone (and, presumably, must then be flushed by the programmer).
  2489.  
  2490.     // EXAMPLE INPUT-25
  2491.  
  2492.     // TEST THE getline() FUNCTION
  2493.  
  2494.     // IN TC++ 1.01 THE ENDING QUOTE
  2495.     // APPEARS ON THE NEXT LINE BE-
  2496.     // CAUSE THE NEWLINE CHARACTER IS
  2497.     // MADE PART OF THE USER'S BUFFER
  2498.     // AREA. IN BORLAND C++ THIS HAS
  2499.     // BEEN CORRECTED
  2500.  
  2501.     #include <header.h>
  2502.  
  2503.     const int length = 100 ;
  2504.  
  2505.     int main()
  2506.     {
  2507.         char string [length] ;
  2508.  
  2509.        cout << "Enter a string: " ;
  2510.        cin.getline(string , length) ;
  2511.        cout << "Your string: "
  2512.           << DOUBLE_QUOTE
  2513.           << string
  2514.           << DOUBLE_QUOTE
  2515.           << "\n" ;
  2516.  
  2517.         return 0 ;
  2518.     }
  2519.  
  2520. ==========================================================
  2521.  
  2522.    It's also possible to find out exactly how many characters were
  2523. extracted from the input buffer after a get() operation. The member
  2524. function gcount() returns this value. In this program if you enter "ABC"
  2525. gcount() will report that 4 characters were read.
  2526.  
  2527. // EXAMPLE INPUT-26
  2528.  
  2529. // DETERMINE HOW MANY CHARACTERS
  2530. // WERE ENTERED
  2531.  
  2532. #include <header.h>
  2533.  
  2534. const int length = 100 ;
  2535.  
  2536. int main()
  2537. {
  2538.    char string[length] ;
  2539.  
  2540.    cout << "Enter a string: " ;
  2541.    cin.getline(string , length) ;
  2542.    cout << "Your string: "
  2543.         << DOUBLE_QUOTE
  2544.         << string
  2545.         << DOUBLE_QUOTE
  2546.         << "\n" ;
  2547.  
  2548.    cout << "You entered "
  2549.         << cin.gcount()
  2550.         << " characters\n" ;
  2551.  
  2552.    return 0 ;
  2553. }
  2554.  
  2555. ==========================================================
  2556.  
  2557. Checking for end-of-file
  2558.  
  2559.    When reading data from the keyboard or a file, the programmer must
  2560. always be on guard for the occurrence of an end-of-file mark (in DOS it's
  2561. the character ^Z or decimal value 26 from text files. In Unix it's
  2562. <CTRL>-D). This is comparable to detecting the return value EOF when
  2563. doing a scanf() in C. In C++, the member function eof() taking no
  2564. arguments in the class ios will return ╥true╙ if the end-of-file
  2565. condition was found, ╥false╙ if not found.
  2566.  
  2567.    Normally data is obtained within a while loop, with the loop
  2568. continuing to execute as long as end-of-file is not detected. This
  2569. situation could be coded like this:
  2570.  
  2571.     // EXAMPLE INPUT-31
  2572.  
  2573.     // ENTER A NUMBER AND LOOP
  2574.     // UNTIL EOF IS DETECTED
  2575.  
  2576.     #include <header.h>
  2577.  
  2578.     int main()
  2579.     {
  2580.      cout << "Enter a number: " ;
  2581.      int num ;
  2582.      cin >> num ;
  2583.        while (!cin.eof())
  2584.        {
  2585.         cout << "You entered: "
  2586.              << num
  2587.              << '\n' ;
  2588.         cout << "\nNext number: " ;
  2589.         cin >> num ;
  2590.        }
  2591.        cout << "End-of-file\n" ;
  2592.  
  2593.        return 0 ;
  2594.     }
  2595.  
  2596. ==========================================================
  2597.  
  2598.    While this program certainly works, there is a better way to code it.
  2599. Since the statement:
  2600.  
  2601.         cin >> num ;
  2602.  
  2603. returns a reference to the invoking object itself (namely cin), this
  2604. object can be used as the invoking object for the eof() member function
  2605. call. Thus, the revised code looks like:
  2606.  
  2607.     // EXAMPLE INPUT-32
  2608.  
  2609.     // A BETTER METHOD OF CODING
  2610.     // EXAMPLE INPUT-31
  2611.  
  2612.     #include <header.h>
  2613.  
  2614.     int main()
  2615.     {
  2616.      cout << "Enter a number: " ;
  2617.      int num ;
  2618.      while (!(cin >> num).eof())
  2619.        {
  2620.         cout << "You entered: "
  2621.              << num
  2622.              << '\n' ;
  2623.             cout << "\nNext number: " ;
  2624.        }
  2625.        cout << "End-of-file\n" ;
  2626.  
  2627.        return 0 ;
  2628.     }
  2629.  
  2630. ==========================================================
  2631.  
  2632.    Notice how the read and check for end-of-file have been combined to
  2633. form the Boolean condition of the while loop. This is analagous in C to
  2634. writing:
  2635.  
  2636.     while(scanf("%d" , &num) != EOF)
  2637.     {
  2638.         /* Body of loop */
  2639.     }
  2640.  
  2641. ==========================================================
  2642.  
  2643. Checking for errors
  2644.  
  2645.    Unfortunately, we live in an imperfect world. People don't smile, cars
  2646. crash, checks bounce, and data entry operators don't always do what
  2647. they're supposed to do. This means that as a programmer you must be
  2648. responsible for making your code as "operator-proof" as possible. In
  2649. other words, no matter what the user may enter as "data", your program
  2650. must capture it and successfully trap all error conditions to avoid such
  2651. catastrophes as ╥garbage in, garbage out╙, aborts, hangs, endless loops,
  2652. etc.
  2653.  
  2654.    When expecting character or string input, there's not too much that
  2655. can go wrong, other than array overflow which has already been covered.
  2656. But with numeric data, such as ints, floats and doubles, only certain
  2657. keystrokes in a prescribed order and considered to be valid. For example,
  2658. when you expect a decimal integer to be input, the user may enter a sign
  2659. (+ or -) followed by the digits 0 through 9. An entry of A12 is obviously
  2660. invalid. An entry such as 12A, however, is considered to be the number
  2661. 12, with the "invalid" character 'A' serving to terminate the numeric
  2662. portion of the input stream. In addition, any whitespace character
  2663. terminates a numeric entry, and all leading whitespace characters are
  2664. bypassed automatically.
  2665.  
  2666.    There are several ways to check for "garbage" input when expecting
  2667. valid numeric data. Within the class ios the member function good() will
  2668. return "true" if the preceding operation succeeded, "false" otherwise. In
  2669. addition, the member function fail() will do just the opposite. The
  2670. member function bad() will report some catastrophic condition, such as a
  2671. corrupted stream.
  2672.  
  2673.    Another way to check for an input error is to use the overloaded
  2674. function operator! (Boolean not) on the instance cin. This operator will
  2675. return "true" if an error occurred, "false" otherwise. Similarly, testing
  2676. the instance cin itself as a Boolean value will return "true" if the
  2677. input was good, "false" otherwise.
  2678.  
  2679.    Note that in the header file header.h the function IOFLAGS() has
  2680. been defined to accept an instance of an input stream as an argument, and
  2681. will display the various input states. The default argument is the
  2682. instance cin. To test this, trying entering some numeric and non-numeric
  2683. data for this program, as well as end-of-file.
  2684.  
  2685.     // EXAMPLE INPUT-41
  2686.  
  2687.     // TEST THE INPUT STREAM STATES
  2688.  
  2689.     #include <header.h>
  2690.  
  2691.     int main()
  2692.     {
  2693.      cout << "Enter a number: " ;
  2694.        int number ;
  2695.      cin >> number ;
  2696.      IOFLAGS() ;
  2697.  
  2698.        return 0 ;
  2699.     }
  2700.  
  2701. ==========================================================
  2702.  
  2703.    Now that you see what does and does not work, the next problem is how
  2704. to eliminate the excess, or garbage, characters from the input stream.
  2705. This can be accomplished by reading 1 character at a time until the
  2706. <RETURN> ('\n') character or end-of-file has been read. (Of course this
  2707. method assumes that if an error condition is encountered, then the
  2708. integrity of the remaining characters in the buffer is in question.) In
  2709. addition, when an error occurs, the status of the input stream is changed
  2710. from ╥good╙ to ╥fail╙ and no more characters can be read until the status
  2711. is reset to ╥good╙. To do this, you must call upon the ios member
  2712. function clear() with no arguments (the default argument is 0, which
  2713. means ╥set the status of the stream to 'good'╙).
  2714.  
  2715.    To save you the trouble of having to code a function to accomplish
  2716. this "flushing" task, the file header.h has an input manipulator called
  2717. FLUSH that will do this for you. (The subject of manipulators and how
  2718. they work will be covered in the chapter MANIP.)
  2719.  
  2720.    Thus, an "operator-proof" program that loops while reading numbers and
  2721. checking for end-of-file and garbage input might resemble this:
  2722.  
  2723.     // EXAMPLE INPUT-42
  2724.  
  2725.     // SHOW HOW TO HANDLE ANYTHING
  2726.     // THE OPERATOR CAN THROW AT
  2727.     // THE PROGRAM
  2728.  
  2729.     #include <header.h>
  2730.  
  2731.     int main()
  2732.     {
  2733.      cout << "\nEnter a number: " ;
  2734.        int number ;
  2735.         while(!(cin >> number).eof())
  2736.      {
  2737.         // Test for a bad number
  2738.         if(!cin)
  2739.         // Same as: if(!cin.good())
  2740.            cout << "Input error!\n" ;
  2741.  
  2742.            // Process a good number
  2743.            else
  2744.                 cout << "YOU ENTERED: "
  2745.                   << number
  2746.                   << '\n' ;
  2747.  
  2748.            // Clear out the input buffer.
  2749.            cin >> FLUSH ;
  2750.  
  2751.            cout << "\nNext number: " ;
  2752.           }
  2753.           cout << "\nEND OF PROGRAM\n" ;
  2754.  
  2755.        return 0 ;
  2756.     }
  2757.  
  2758.    One note about the logic of this program. If 2 valid numbers are
  2759. entered before the operator presses <RETURN>, then only the first number
  2760. will be processed; the second will be flushed. You may or may not want
  2761. this to happen, depending upon your design philosophy.
  2762.  
  2763. ==========================================================
  2764.  
  2765. Incore input
  2766.  
  2767.    Incore input refers to how you can read input from an in-memory buffer
  2768. of type char* instead of from the keyboard.
  2769.  
  2770.    In C this is done by using the function sscanf(), where the first
  2771. argument specifies the address of the buffer area from which the data is
  2772. to be read. For example:
  2773.  
  2774. // EXAMPLE INPUT-51
  2775.  
  2776. // HOW TO DO INCORE INPUT USING C
  2777.  
  2778. #include <header.h>
  2779.  
  2780. int main(void)
  2781. {
  2782.    char buffer[] = "ABC 1.234 5" ;
  2783.    char string[100] ;
  2784.    /* Initialized to link floating point formats */
  2785.    float f = sqrt(0.0) ;
  2786.    int n ;
  2787.  
  2788.    sscanf(buffer , "%s%f%d" , string , &f , &n) ;
  2789.    printf("string = %c%s%c\n" ,
  2790.            DOUBLE_QUOTE ,
  2791.            string ,
  2792.            DOUBLE_QUOTE) ;
  2793.    printf("float = %f\n" , f) ;
  2794.    printf("int = %d\n" , n) ;
  2795.  
  2796.    return 0 ;
  2797. }
  2798.  
  2799. =========================================================
  2800.  
  2801.    In order to accomplish the same result in C++ you must first include
  2802. the header file strstream.h (this is already done in the file
  2803. header.h). This file contains the declaration of the class istrstream,
  2804. which you then use to create some instance. At the time of creation, you
  2805. must provide two arguments: (1) the address of the buffer from which the
  2806. data is to be read, and (2) the maximum size of this buffer (which
  2807. normally is the sizeof the buffer). For example,
  2808.  
  2809.     char buffer[80] ;
  2810.     istrstream input(buffer , sizeof buffer) ;
  2811.  
  2812.    After this has been done, the instance input is used where you would
  2813. normally use cin. All of the data is thus read from the buffer area. If
  2814. you subsequently wish to read this buffer area starting back at character
  2815. position 0, you must use the (inherited) member function seekg() with an
  2816. argument of 0.
  2817.  
  2818. // EXAMPLE INPUT-52
  2819.  
  2820. // HOW TO DO INCORE INPUT USING C++
  2821.  
  2822. #include <header.h>
  2823.  
  2824. int main(void)
  2825. {
  2826.    char buffer[] = "ABC 1.234 5" ;
  2827.    char string[100] ;
  2828.    float f ;
  2829.    int n ;
  2830.  
  2831.    istrstream input(buffer , sizeof buffer) ;
  2832.  
  2833.    input >> string >> f >> n ;
  2834.    cout << "string = "
  2835.          << DOUBLE_QUOTE
  2836.          << string
  2837.          << DOUBLE_QUOTE
  2838.          << endl ;
  2839.    cout << "float = " << f << endl ;
  2840.    cout << "int = " << n << endl ;
  2841.  
  2842.    // Let's do it again
  2843.    input.seekg(0) ;
  2844.    input >> string >> f >> n ;
  2845.    cout << "string = "
  2846.          << DOUBLE_QUOTE
  2847.          << string
  2848.          << DOUBLE_QUOTE
  2849.          << endl ;
  2850.    cout << "float = " << f << endl ;
  2851.    cout << "int = " << n << endl ;
  2852.  
  2853.    return 0 ;
  2854. }
  2855.  
  2856. =========================================================
  2857.  
  2858.    If you wish to do both input and output using a memory buffer, one way
  2859. is to create an instance of the class strstream, but with no arguments,
  2860. e.g.,
  2861.  
  2862.      strstream both ;
  2863.  
  2864. When the instance both is used, data is stored in an internal buffer
  2865. area. The extraction operator may then be used with the instance to read
  2866. from this buufer area. In addition, the function rdbuf() returns the
  2867. address of the buffer area.
  2868.  
  2869. // EXAMPLE INPUT-53
  2870.  
  2871. // HOW TO DO BOTH INPUT AND OUTPUT
  2872. // WITH AN IN-CORE BUFFER
  2873.  
  2874. #include <header.h>
  2875.  
  2876. int main()
  2877. {
  2878.    strstream both ;
  2879.  
  2880.    // Put data into the internal
  2881.    // buffer
  2882.    both << "ABC"
  2883.         << " " << 1.234
  2884.         << " " << 5
  2885.         << ends ;
  2886.  
  2887.    // The data so far:
  2888.    cout << both.rdbuf() << endl ;
  2889.  
  2890.    // Don't forget this
  2891.    both.seekg(0) ;
  2892.  
  2893.    // Extract data from 'buffer'
  2894.  
  2895.    char string[100] ;
  2896.    float f ;
  2897.    int n ;
  2898.    both >> string >> f >> n ;
  2899.  
  2900.    // Verify the data
  2901.    cout << "string = "
  2902.         << DOUBLE_QUOTE
  2903.         << string
  2904.         << DOUBLE_QUOTE
  2905.         << endl ;
  2906.    cout << "float = " << f << endl ;
  2907.    cout << "int = " << n << endl ;
  2908. }
  2909.  
  2910. =========================================================
  2911.  
  2912.    If you wish to create your own buffer area, then you may do so
  2913. provided that you open the internal file in both input and output modes
  2914. (see the chapter FILEIO for more information on file modes).
  2915.  
  2916. // EXAMPLE INPUT-54
  2917.  
  2918. // HOW TO DO BOTH INPUT AND OUTPUT
  2919. // WITH A USER-DEFINED BUFFER
  2920.  
  2921. #include <header.h>
  2922.  
  2923. int main()
  2924. {
  2925.    char buffer[100] ;
  2926.    strstream both(buffer , sizeof buffer , ios::in | ios::out) ;
  2927.  
  2928.    // Put data into 'buffer'
  2929.    both << "ABC"
  2930.         << " " << 1.234
  2931.         << " " << 5
  2932.         << ends ;
  2933.  
  2934.    // The data so far:
  2935.    cout << buffer << endl ;
  2936.  
  2937.    // Don't forget this
  2938.    both.seekg(0) ;
  2939.  
  2940.    // Extract data from 'buffer'
  2941.    char string[100] ;
  2942.    float f ;
  2943.    int n ;
  2944.    both >> string >> f >> n ;
  2945.  
  2946.    // Verify the data
  2947.    cout << "string = "
  2948.         << DOUBLE_QUOTE
  2949.         << string
  2950.         << DOUBLE_QUOTE
  2951.         << endl ;
  2952.    cout << "float = " << f << endl ;
  2953.    cout << "int = " << n << endl ;
  2954. }
  2955.  
  2956. ============================================================================
  2957. ============================================================================
  2958.  
  2959.                            CHAPTER 4 -- Manipulators
  2960.  
  2961. Introduction
  2962.  
  2963.    As you have probably noticed by now, the elimination of conversion
  2964. specifications (%d, %c, etc.) found in the scanf() and printf()
  2965. functions in C causes you to do a lot of extra coding to accomplish the
  2966. same end result. For example, to output a number in hex, the
  2967. specification %x does the job in a printf() statement, but using the
  2968. functions supplied in iostream.h you have to write:
  2969.  
  2970.     cout.setf(ios::hex , ios::basefield) ;
  2971.  
  2972. even before you get around to outputting the number itself.
  2973.  
  2974.    Fortunately, the input and output stream classes provide the
  2975. capability to eliminate much of this tedious coding, as well as a method
  2976. to combine the setting of the stream state with the actual outputting (or
  2977. inputting) of the data itself. This method uses what is called a
  2978. manipulator. The term comes from the fact that a manipulator does just
  2979. what it implies ╤ it manipulates, or changes, the state of the stream.
  2980.  
  2981.    In the same sense that a call of a function causes that function to do
  2982. any number of individual tasks the programmer may specify, a manipulator
  2983. is also a function that sets the stream state. The input and output
  2984. classes come with some manipulators already built in, and a nice feature
  2985. is that you can easily define your own.
  2986.  
  2987.    The one peculiar aspect about manipulators is that they are always
  2988. called "indirectly" by a separate function in the class ios. This other
  2989. function "knows" which individual manipulator to call because it takes
  2990. the manipulator's address as its one formal argument. How does it get
  2991. this address? When the name of a function is written without the open and
  2992. close parentheses, the compiler generates the address of the function
  2993. instead of actually calling the function. This address can, in turn, be
  2994. passed as an argument to another function. Of course, this address must
  2995. be stored into a variable declared as ╥pointer to function╙ which has the
  2996. proper return type and argument list.
  2997.  
  2998.    One of the main advantages to using manipulators is that they can be
  2999. chained together, just like any other type of argument you may want to
  3000. input or output. Consider this problem: Write code to output the number
  3001. 123, then set the field width to 5, then set the fill character to an
  3002. '*', then output the number 456. Using the functions we've learned up to
  3003. now, you might be tempted to write the code:
  3004.  
  3005.      cout << 123 << cout.width(5) << cout.fill('*') << 456 << '\n' ;
  3006.  
  3007. If you do, you will see:
  3008.  
  3009.     ***1230 456
  3010.  
  3011. instead of:
  3012.  
  3013.     123**456
  3014.  
  3015.    Of course, one way to fix this problem is to segregate the calls to
  3016. the member functions from the calls to the insertion operator. Thus:
  3017.  
  3018.     cout << 123 ;
  3019.     cout.width(5) ;
  3020.     cout.fill('*') ;
  3021.     cout << 456 << '\n' ;
  3022.  
  3023. This produces the correct output, but it's "choppy" because one "thought"
  3024. now has to be written in four separate output statements.
  3025.  
  3026.    But since the manipulators that handle input and output stream states
  3027. can be chained with other arguments, then (assuming output) generically
  3028. they have the form:
  3029.  
  3030.     cout << data-item1 << manipulator << data-item2 ;
  3031.  
  3032. Thus, if the manipulator could be made to set the field width to 5 and
  3033. the fill character to '*', our problem could be coded in a much more
  3034. concise manner. In addition, manipulators must not return any value that
  3035. might cause unwanted output to appear.
  3036.  
  3037.    In order to preserve the ability to chain successive calls to the
  3038. insertion operator function, each manipulator function must adhere to the
  3039. rule that the invoking instance is always passed in by reference and
  3040. returned by reference. This means that all output manipulator functions
  3041. have the format:
  3042.  
  3043.     ostream& manipulator_name(ostream& strm)
  3044.     {
  3045.          // your code here
  3046.         return strm ;
  3047.     }
  3048.  
  3049.    In a similar fashion, all input manipulators have the format:
  3050.  
  3051.     istream& manipulator_name(istream& strm)
  3052.     {
  3053.          // your code here
  3054.         return strm ;
  3055.     }
  3056.  
  3057.    To accommodate an argument of type "pointer to function", the class
  3058. ostream has an overloaded insertion operator function similar to this
  3059. code:
  3060.  
  3061.     ostream& operator<<(ostream& (*ptr)(ostream&))
  3062.     {
  3063.         return (*ptr)(*this) ;
  3064.     }
  3065.  
  3066.    The class istream has an overloaded extraction operator function
  3067. similar to this code:
  3068.  
  3069.     istream& operator>>(istream& (*ptr)(istream&))
  3070.     {
  3071.         return (*ptr)(*this) ;
  3072.     }
  3073.  
  3074.    It's these two functions that call upon your manipulator function
  3075. whose address has been stored into the pointer variable ptr. *this
  3076. refers to the invoking instance itself, and will be discussed at length
  3077. in the CLASSB chapter.
  3078.  
  3079.    As a test, here is a program that creates a manipulator function
  3080. called manip that sets the field width to 5 and the fill character to
  3081. '*'.
  3082.  
  3083. ==========================================================
  3084.  
  3085.     // EXAMPLE MANIP-01
  3086.  
  3087.     // HOW TO CREATE YOUR OWN
  3088.     // MANIPULATOR
  3089.  
  3090.     #include <header.h>
  3091.  
  3092.     ostream& manip(ostream& strm)
  3093.     {
  3094.        strm.width(5) ;
  3095.        strm.fill('*') ;
  3096.        return strm ;
  3097.     }
  3098.  
  3099.     int main()
  3100.     {
  3101.      cout << manip
  3102.           << 23
  3103.           << '\n' ;
  3104.  
  3105.        return 0 ;
  3106.     }
  3107.  
  3108. The output of this program is:
  3109.  
  3110.     ***23
  3111.  
  3112. ==========================================================
  3113.  
  3114. Built-in manipulators taking no arguments
  3115.  
  3116.    Because some output (and input) stream manipulations are done so
  3117. frequently, the header file iostream.h includes some pre-defined
  3118. manipulators. These manipulators may take no arguments, or 1 argument.
  3119. Let's first consider some built-in manipulators that take no arguments.
  3120.  
  3121.    As the first example, the manipulator endl is designed to output a new
  3122. line character and flush the output buffer. Use may use this in place of
  3123. '\n'. For example:
  3124.  
  3125.     // EXAMPLE MANIP-02
  3126.  
  3127.     // THE endl MANIPULATOR
  3128.  
  3129.     #include <header.h>
  3130.  
  3131.     int main()
  3132.     {
  3133.           cout << 1
  3134.             << endl
  3135.               << 2
  3136.               << endl ;
  3137.  
  3138.        return 0 ;
  3139.     }
  3140.  
  3141. The output of this program is:
  3142.  
  3143. 1
  3144. 2
  3145.  
  3146. ==========================================================
  3147.  
  3148.    The manipulators dec, oct and hex work for both input and output
  3149. operations, and set the stream state accordingly. NOTE: Using Borland C++
  3150. by Atkinson and Atkinson, page 732, says that the hex portion of the
  3151. following program will not work. In fact, it works just fine.
  3152.  
  3153.     // EXAMPLE MANIP-03
  3154.  
  3155.     // SETTING THE STREAM STATES USING
  3156.     // MANIPULATORS
  3157.  
  3158.     #include <header.h>
  3159.  
  3160.     int main()
  3161.     {
  3162.      cout << "Input a hex number: " ;
  3163.      int number ;
  3164.      cin >> hex
  3165.          >> number ;
  3166.      cout << "The number in hex is "
  3167.           << hex
  3168.           << number
  3169.           << endl ;
  3170.      cout << "The number in octal is "
  3171.           << oct
  3172.           << number
  3173.           << endl ;
  3174.  
  3175.        return 0 ;
  3176.     }
  3177.  
  3178. If you enter the number ff (hex), you will then see the numbers ff (hex)
  3179. and 377 (octal).
  3180.  
  3181. ==========================================================
  3182.  
  3183.    Recall that when using the function get() with 3 arguments to read in
  3184. a string, both leading and embedded whitespace are retained. If you want
  3185. to bypass the leading whitespace, and still retain the embedded
  3186. whitespace, then use the input manipulator ws. Note, however, that it is
  3187. effective only for the next input operation, after which another get()
  3188. would retain leading whitespace.
  3189.  
  3190.    In this program enter some leading whitespace, then some significant
  3191. characters including embedded whitespace.
  3192.  
  3193.     // EXAMPLE MANIP-04
  3194.  
  3195.     // DEMONSTRATE HOW TO READ IN A
  3196.     // STRING AND RETAIN EMBEDDED
  3197.     // WHITE SPACE, BUT BYPASS
  3198.     // LEADING WHITE SPACE
  3199.  
  3200.     #include <header.h>
  3201.  
  3202.     const int length = 100 ;
  3203.  
  3204.     int main()
  3205.     {
  3206.      char string[length] ;
  3207.  
  3208.      cout << "Enter a string: " ;
  3209.      cin >> ws ;
  3210.      cin.get(string , length) ;
  3211.      cout << "Your string: "
  3212.           << DOUBLE_QUOTE
  3213.           << string
  3214.           << DOUBLE_QUOTE
  3215.           << endl ;
  3216.  
  3217.        return 0 ;
  3218.     }
  3219.  
  3220. ==========================================================
  3221.  
  3222.    Another built-in manipulator that takes no argument is called ends.
  3223. This causes a null character to be output, and is useful for objects of
  3224. type strstream. Here is example OUTPUT-96 again, this time using ends.
  3225.  
  3226.     // EXAMPLE MANIP-05
  3227.  
  3228.     // HOW TO DO INCORE OUTPUT IN C++
  3229.     // (SAME AS OUTPUT-96 , BUT NOW THE
  3230.     // MANIPULATOR ends IS USED)
  3231.  
  3232.     #include <header.h>
  3233.  
  3234.     int main()
  3235.     {
  3236.      int number = 123 ;
  3237.      char buffer[80] ;
  3238.  
  3239.      ostrstream output(buffer , sizeof buffer);
  3240.  
  3241.      output << "number is "
  3242.             << number
  3243.             << ends ;
  3244.      cout << DOUBLE_QUOTE
  3245.           << buffer
  3246.           << DOUBLE_QUOTE
  3247.           << '\n' ;
  3248.  
  3249.      output.seekp(0) ;
  3250.      output << "A new buffer stream "
  3251.             << "of characters"
  3252.             << ends ;
  3253.      cout << DOUBLE_QUOTE
  3254.           << buffer
  3255.           << DOUBLE_QUOTE
  3256.           << '\n' ;
  3257.  
  3258.      return 0 ;
  3259.     }
  3260.  
  3261. ==========================================================
  3262.  
  3263.    The last manipulator that takes no input argument is called flush.
  3264. This causes the stream associated with the output instance to be
  3265. completely emptied. In point of fact, you probably will never need to use
  3266. this manipulator for several reasons. First, recall that the bit
  3267. ios::unitbuf in the class ios is on by default. This causes all output
  3268. streams to be flushed automatically whenever there is data in them.
  3269. Second, the stream ostream is "tied" to the stream istream by the
  3270. function call:
  3271.  
  3272.     cin.tie(&cout) ;
  3273.  
  3274. so that whenever the operator needs to enter some data from the keyboard,
  3275. any prompting information in the output stream is guaranteed to appear on
  3276. the terminal screen. to "untie" these stream, you may call the tie()
  3277. function with a value of zero.
  3278.  
  3279.    Therefore, if you really want to avoid flushing the output stream, you
  3280. must (a) turn off the bit ios::unitbuf, and (b) untie the streams.
  3281.  
  3282.    In this example, the prompt does not appear before the operator must
  3283. enter a number.
  3284.  
  3285. ==========================================================
  3286.  
  3287.     // EXAMPLE MANIP-06
  3288.  
  3289.     // HOW TO AVOID FLUSHING THE OUTPUT
  3290.     // STREAM AUTOMATICALLY
  3291.  
  3292.     #include <header.h>
  3293.  
  3294.     int main()
  3295.     {
  3296.        cout.unsetf(ios::unitbuf) ;
  3297.        cin.tie(0) ;
  3298.  
  3299.        cout << "Enter a number: " ;
  3300.        int number ;
  3301.        cin >> number ;
  3302.        cout << "You entered: "
  3303.           << number
  3304.           << endl ;
  3305.  
  3306.        return 0 ;
  3307.     }
  3308.  
  3309. ==========================================================
  3310.  
  3311. But now let's add the flush manipulator.
  3312.  
  3313.     // EXAMPLE MANIP-07
  3314.  
  3315.     // ADD THE flush MANIPULATOR TO
  3316.     // FORCE THE PROMPT TO APPEAR
  3317.  
  3318.     #include <header.h>
  3319.  
  3320.     int main()
  3321.     {
  3322.        cout.unsetf(ios::unitbuf) ;
  3323.        cin.tie(0) ;
  3324.  
  3325.        cout << "Enter a number: "
  3326.           << flush ;
  3327.        int number ;
  3328.        cin >> number ;
  3329.        cout << "You entered: "
  3330.           << number
  3331.           << endl ;
  3332.  
  3333.        return 0 ;
  3334.     }
  3335.  
  3336. ==========================================================
  3337.  
  3338. Built-in manipulators taking 1 argument
  3339.  
  3340.    Because a manipulator that takes 1 argument requires special handling
  3341. by the compiler, a separate header file must be included with each
  3342. program. This file is called iomanip.h. Note that in the file header.h
  3343. it is automatically included.
  3344.  
  3345.    Perhaps the most frequently used manipulator taking an argument is
  3346. setw. Like its counterpart, the member function width(), it is used to
  3347. set the field width for the next output item only. But since manipulators
  3348. are designed to be coded "in line" with data to be output, they do not
  3349. return a value (which would cause spurious data to appear in the output
  3350. buffer). The one argument is, of course, the field width itself.
  3351.  
  3352.    Here is example OUTPUT-41 again, this time using a manipulator to set
  3353. the field width.
  3354.  
  3355.     // EXAMPLE MANIP-11
  3356.  
  3357.     // HOW TO SET THE FIELD WIDTH
  3358.     // USING A MANIPULATOR
  3359.  
  3360.     #include <header.h>
  3361.  
  3362.     int main()
  3363.     {
  3364.      cout << setw(5)
  3365.           << 1
  3366.           << endl ;
  3367.      cout << setw(5)
  3368.           << 23
  3369.           << endl ;
  3370.  
  3371.        return 0 ;
  3372.     }
  3373.  
  3374. The output of this program is:
  3375.  
  3376.         1
  3377.        23
  3378.  
  3379. ==========================================================
  3380.  
  3381.    Another frequently used manipulator is the one that sets the fill
  3382. character. It is called setfill and, as you would expect, the 1 argument
  3383. is the fill character itself.
  3384.  
  3385.    Here is example OUTPUT-52 again, this time using manipulators to set
  3386. the field width and fill character.
  3387.  
  3388.     // EXAMPLE MANIP-12
  3389.  
  3390.     // A COMBINATION OF SETTING THE
  3391.     // FIELD WIDTH AND SPECIFYING
  3392.     // THE FILL CHARACTER USING
  3393.     // MANIPULATORS
  3394.  
  3395.     #include <header.h>
  3396.  
  3397.     int main()
  3398.     {
  3399.      cout << setw(5)
  3400.           << setfill('0')
  3401.               << 1
  3402.                << endl ;
  3403.      cout << setw(5)
  3404.                << setfill('*')
  3405.                << 23
  3406.           << endl ;
  3407.  
  3408.        return 0 ;
  3409.     }
  3410.  
  3411. The output of this program is:
  3412.  
  3413.     0001
  3414.     ***23
  3415.  
  3416. ==========================================================
  3417.  
  3418.    The other manipulators that take an argument are:
  3419.  
  3420. resetiosflags(long flag) -- turns off the bits specified in flag
  3421.                             (input and output)
  3422. setbase(int base) -- sets the output base to decimal if base if 0 or
  3423.                      10; to octal if base is 8; to hexadecimal if base is 16
  3424.                      (output)
  3425. setiosflags(long flag) -- turns on the bits specified in flag (input
  3426.                           and output)
  3427. setprecision(int prec) -- sets the number of digits displayed after the
  3428.                           decimal point to prec (output)
  3429.  
  3430. ==========================================================
  3431.  
  3432. Creating your own manipulators taking 1 argument
  3433.  
  3434.    The explanation of how manipulators taking 1 argument are handled by
  3435. the compiler is too complex to be explained here, so let's just see how
  3436. it is coded.
  3437.  
  3438.    First, the generic form (assuming output) of the manipulator is:
  3439.  
  3440.     ostream& manipulator-name(ostream& strm , type arg)
  3441.     {
  3442.          // your code here using arg
  3443.         return strm ;
  3444.     }
  3445.  
  3446. where type is either int or long, and arg is the formal argument name.
  3447.  
  3448.    Next, you must include this code:
  3449.  
  3450.     OMANIP(type) manipulator-name(type arg)
  3451.     {
  3452.        return OMANIP(type) (manipulator-name , arg) ;
  3453.     }
  3454.  
  3455. where OMANIP is a class defined in iomanip.h.
  3456.  
  3457.    For example, here is a manipulator called manip that sets the field
  3458. width to whatever the argument happens to be, and also sets the fill
  3459. character to '*'.
  3460.  
  3461.     // EXAMPLE MANIP-13
  3462.  
  3463.     // HOW TO CREATE A MANIPULATOR THAT
  3464.     // TAKES 1 ARGUMENT
  3465.  
  3466.     #include <header.h>
  3467.  
  3468.     ostream& manip(ostream& strm , int length)
  3469.     {
  3470.      strm << setw(length) << setfill('*') ;
  3471.      return strm ;
  3472.     }
  3473.  
  3474.     OMANIP(int) manip(int length)
  3475.     {
  3476.      return OMANIP(int) (manip , length) ;
  3477.     }
  3478.  
  3479.     int main()
  3480.     {
  3481.      cout << manip(7)
  3482.           << 123
  3483.           << endl ;
  3484.      cout << manip(5)
  3485.           << 45
  3486.           << endl ;
  3487.  
  3488.        return 0 ;
  3489.     }
  3490.  
  3491. The output of this program is:
  3492.  
  3493. ****123
  3494. ***45
  3495.  
  3496. ==========================================================
  3497.  
  3498.    If you wish to use a type other than int or long, then you must
  3499. include the following statement:
  3500.  
  3501.     IOMANIPdeclare(type) ;
  3502.  
  3503. where type is either char, float, double, etc. If the type is "pointer
  3504. to", then it must be typedef'ed before using.
  3505.  
  3506.    Here is the same example, but now it is the fill character that is
  3507. variable.
  3508.  
  3509.     // EXAMPLE MANIP-14
  3510.  
  3511.     // HOW TO CREATE A MANIPULATOR THAT
  3512.     // TAKES 1 ARGUMENT, AND THAT ARGUMENT
  3513.     // IS NOT int OR long
  3514.  
  3515.     #include <header.h>
  3516.  
  3517.     // Don't forget this statement
  3518.     IOMANIPdeclare(char) ;
  3519.  
  3520.     ostream& manip(ostream& strm , char ch)
  3521.     {
  3522.      strm << setw(7) << setfill(ch) ;
  3523.      return strm ;
  3524.     }
  3525.  
  3526.     OMANIP(char) manip(char ch)
  3527.   {  
  3528.      return OMANIP(char) (manip , ch) ;
  3529.     }
  3530.  
  3531.     int main()
  3532.     {
  3533.      cout << manip('*')
  3534.           << 123
  3535.           << endl ;
  3536.      cout << manip('$')
  3537.           << 45
  3538.           << endl ;
  3539.  
  3540.        return 0 ;
  3541.     }
  3542.  
  3543. The output of this program is:
  3544.  
  3545. ****123
  3546. $$$$$45
  3547.  
  3548. ==========================================================
  3549.  
  3550.    Finally, take a look at the header.h file for some useful manipulators
  3551. that have already been defined for you.
  3552.  
  3553. ============================================================================
  3554. ============================================================================
  3555.  
  3556.                             CHAPTER 5 -- File I/O
  3557.  
  3558. Introduction
  3559.  
  3560.    File input/output using AT&T version 2.0 involves any of these 3
  3561. operations:
  3562.  
  3563.   1) Reading a file
  3564.   2) Writing a file
  3565.   3) Both reading and writing a file
  3566.  
  3567.    To handle these operations, special classes have already been defined.
  3568. They are:
  3569.  
  3570.     Read -- class ifstream (derived from istream)
  3571.     Write -- class ofstream (derived from ostream)
  3572.     Both -- class fstream (derived from iostream)
  3573.  
  3574.    To use any of these classes, you must have the following statement:
  3575.  
  3576.     #include <fstream.h>
  3577.  
  3578. which automatically includes the header file iostream.h. (The file
  3579. fstream.h is already included in header.h.)
  3580.  
  3581.    There are no pre-defined instances of these classes comparable to cin
  3582. and cout.Therefore, the first step in using file I/O is to create an
  3583. instance of the appropriate class, e.g.,
  3584.  
  3585.     ifstream file_in ;
  3586.      ofstream file_out ;
  3587.      fstream file_both ;
  3588.  
  3589. ========================================================
  3590.  
  3591. Using the instances
  3592.  
  3593.    The first step in using the file instances is to open a disk file. In
  3594. any computer language this means establishing a communication link
  3595. between your code and the external file. Each of the 3 classes provides
  3596. the member function called open to do this. The declarations for these
  3597. open functions are as follows:
  3598.  
  3599.     void ifstream::open(const char* name ,
  3600.                       int m = ios::in ,
  3601.                       int prot = filebuf::openprot) ;
  3602.  
  3603.     void ofstream::open(const char* name ,
  3604.                       int m = ios::out ,
  3605.                       int prot = filebuf::openprot) ;
  3606.  
  3607.     void fstream::open(const char* name ,
  3608.                      int m ,
  3609.                      int prot = filebuf::openprot) ;
  3610.  
  3611.    The first argument is the external file name passed in as a constant
  3612. string literal.
  3613.  
  3614.    The second argument is the file mode, and comes from a public
  3615. enumerated type in the class ios. There are eight possible modes, as
  3616. follows:
  3617.  
  3618.      ios::in          Input mode. (Default for input file.)
  3619.      ios::out         Output mode. (Default for output file.)
  3620.      ios::app         Append to an output file rather than update
  3621.                       an existing record.
  3622.      ios::ate         Position file marker at end of file instead of beginning.
  3623.      ios::trunc       Delete file if it exists and re-create it.
  3624.      ios::nocreate    File must exist, otherwise open fails (output only)
  3625.      ios::noreplace   File must not exist, otherwise open fails (output only)
  3626.      ios::binary      Binary mode; default is text (Binary is a Borland 
  3627.                       enhancement)
  3628.  
  3629. Note that for fstream instances, there is no default mode. Obviously,
  3630. these various modes may be bitwise ORed together if more than one is
  3631. desired.
  3632.  
  3633.    The third argument is the file access. Under Borland C++ the possible
  3634. values are:
  3635.  
  3636.     0 = Default
  3637.        1 = Read-only file
  3638.     2 = Hidden file
  3639.     4 = System file
  3640.     8 = Archive bit set
  3641.  
  3642. If the open fails, the overloaded operator ! used on the instance will
  3643. return "true". If the open succeeded, the instance itself will return
  3644. "true".
  3645.  
  3646. For example:
  3647.  
  3648.        file_in.open("INPUT") ;
  3649.        file_out.open("OUTPUT") ;
  3650.     file_both.open("BOTH" , ios::in | ios::out) ;
  3651.  
  3652.    An alternate method of calling the open function is to call the
  3653. constructor with the same argument(s) that you would use for the open().
  3654. Thus, instead of creating the instance and then explicitly calling the
  3655. open() function, you can combine these two steps by writing:
  3656.  
  3657.     ifstream file_in("INPUT") ;
  3658.     ofstream file_out("OUTPUT") ;
  3659.     fstream file_both("BOTH", ios::in | ios::out) ;
  3660.  
  3661.    When you are done using the file, the member function close() taking
  3662. no arguments will close it. This function is called automatically by the
  3663. destructor for the class, but you may call it explicitly if you wish.
  3664.  
  3665.    Let's start with a simple program that accepts string input from the
  3666. user and writes it to a disk file called OUTPUT.DAT.
  3667.  
  3668. // EXAMPLE FILEIO-01
  3669.  
  3670. // CREATE AN OUTPUT FILE AND WRITE
  3671. // WHATEVER DATA THE OPERATOR MAY
  3672. // ENTER
  3673.  
  3674. #include <header.h>
  3675.  
  3676. const int max = 100 ;
  3677.  
  3678. int main()
  3679. {
  3680.    char buffer[max] ;
  3681.    ofstream file_out("OUTPUT.DAT") ;
  3682.    if(!file_out)
  3683.    {
  3684.       cout << "OPEN FAILED\n" ;
  3685.       PAUSE() ;
  3686.       exit(1) ;
  3687.    }
  3688.  
  3689.    cout << "Enter a line of data: " ;
  3690.    while(!cin.get(buffer , max).eof())
  3691.    {
  3692.       file_out << buffer << endl ;
  3693.       cout << "Next line: " ;
  3694.       cin >> FLUSH ;
  3695.    }
  3696.  
  3697.    return 0 ;
  3698. }
  3699.  
  3700. ==========================================================
  3701.  
  3702.    Now give the user a chance to append more records to the file. Note
  3703. that the mode of the file is ios::out | ios::app (although ios::app by
  3704. itself would still have worked).
  3705.  
  3706. // EXAMPLE FILEIO-02
  3707.  
  3708. // GIVE THE USER A CHANCE TO APPEND
  3709. // RECORDS TO THE FILE
  3710.  
  3711. #include <header.h>
  3712.  
  3713. const int max = 100 ;
  3714.  
  3715. ////////////////////////////////////
  3716.  
  3717. int main()
  3718. {
  3719.    char buffer[max] ;
  3720.    ofstream file_out("OUTPUT.DAT" , ios::out | ios::app) ;
  3721.    if(!file_out)
  3722.    {
  3723.       cout << "OPEN FAILED\n" ;
  3724.       PAUSE() ;
  3725.       exit(1) ;
  3726.    }
  3727.  
  3728.    cout << "Enter a line of data: " ;
  3729.    while(!cin.get(buffer , max).eof())
  3730.    {
  3731.       file_out << buffer << endl ;
  3732.       cout << "Next line: " ;
  3733.       cin >> FLUSH ;
  3734.    }
  3735.  
  3736.    return 0 ;
  3737. }
  3738.  
  3739. ==========================================================
  3740.  
  3741.    Finally, this program numbers and prints the records that were just
  3742. written.
  3743.  
  3744. // EXAMPLE FILEIO-03
  3745.  
  3746. // NOW READ THE FILE THAT WAS JUST
  3747. // CREATED
  3748.  
  3749. #include <header.h>
  3750.  
  3751. const int max = 100 ;
  3752.  
  3753. ////////////////////////////////////
  3754.  
  3755. int main()
  3756. {
  3757.    char buffer[max] ;
  3758.    ifstream file_in("OUTPUT.DAT") ;
  3759.    if(!file_in)
  3760.    {
  3761.       cout << "OPEN FAILED\n" ;
  3762.       PAUSE() ;
  3763.       exit(1) ;
  3764.    }
  3765.  
  3766.    int rec = 0 ;
  3767.    while(!file_in.get(buffer , max).eof())
  3768.    {
  3769.       cout << "Record #"
  3770.            << ++rec
  3771.            << ": "
  3772.            << buffer
  3773.            << endl ;
  3774.       file_in >> FLUSH ;
  3775.    }
  3776.  
  3777.    return 0 ;
  3778. }
  3779.  
  3780. ==========================================================
  3781.  
  3782. The file position markers
  3783.  
  3784.    So that the file I/O classes can keep track of where in a file the
  3785. data is to be written to and read from, they establish what is called a
  3786. "file position marker" (fpm). On Turbo C++ this marker has been
  3787. typedefed as a long integer representing an offset value from the
  3788. beginning of the file. In point of fact, there are two such markers, one
  3789. for reading, and one for writing. You may alter these markers by using
  3790. two member functions: seekg() and seekp().  seekg() is associated with
  3791. the file's "get or read" pointer, and seekp() with the file's "put or
  3792. write" pointer. The declarations for these two functions are as follows:
  3793.  
  3794.     istream& istream::seekg(streampos offset) ;
  3795.   istream& istream::seekg(streamoff offset , seek_dir) ;
  3796.  
  3797.     ostream& ostream::seekp(streampos offset) ;
  3798.   ostream& ostream::seekp(streamoff offset , seek_dir) ;
  3799.  
  3800. where streampos and streamoff represent long integers, and seek_dir is
  3801. an enumerated type defined as follows:
  3802.  
  3803.     enum seek_dir {ios::beg , ios::cur , ios::end} ;
  3804.  
  3805. If the 1-argument form of the function is used, then offset is the offset
  3806. from the beginning of the file. If the 2-argument form is used, then
  3807. offset is the offset number of bytes (positive or negative) from the
  3808. absolute seek_dir position. Therefore, a call to seekg() with an
  3809. argument of 0 causes the file to rewind and data to be read starting with
  3810. the first record.
  3811.  
  3812.    To find out the positions of these markers, you may use the member
  3813. functions tellg() and tellp(). They are declared as follows:
  3814.  
  3815.     streampos istream::tellg() ;
  3816.     streampos ostream::tellp() ;
  3817.  
  3818. The first character of a record is deemed to be in position 0. Note that
  3819. for text files a newline character is actually stored as 2 characters: a
  3820. newline ('\n') and a carriage return ('\r').
  3821.  
  3822.    To illustrate this, here is the previous example of writing and
  3823. reading a file, but now it uses an instance of the class fstream so that
  3824. the output and input can be combined. After each record is read and
  3825. printed, the file position marker (fpm) is displayed.
  3826.  
  3827. // EXAMPLE FILEIO-04
  3828.  
  3829. // HOW TO WRITE AND READ A FILE IN
  3830. // THE SAME PROGRAM
  3831.  
  3832. #include <header.h>
  3833.  
  3834. const int max = 100 ;
  3835.  
  3836. ////////////////////////////////////
  3837.  
  3838. int main()
  3839. {
  3840.    char buffer[max] ;
  3841.    fstream file_both("BOTH.DAT" ,
  3842.                       ios::in |
  3843.                       ios::out |
  3844.                       ios::trunc ) ;
  3845.    if(!file_both)
  3846.    {
  3847.       cout << "OPEN FAILED\n" ;
  3848.       PAUSE() ;
  3849.       exit(1) ;
  3850.    }
  3851.  
  3852.    cout << "Enter a line of data: " ;
  3853.    while(!cin.get(buffer , max).eof())
  3854.    {
  3855.       file_both << buffer << endl ;
  3856.       cout << "Next line: " ;
  3857.       cin >> FLUSH ;
  3858.    }
  3859.  
  3860.    // Flush the output buffer
  3861.    file_both << flush ;
  3862.  
  3863.    // Return to the start of the file
  3864.    file_both.seekg(0) ;
  3865.  
  3866.    // Read and print the records, and
  3867.    // show the file position marker
  3868.    int rec = 0 ;
  3869.    while(!file_both.get(buffer , max).eof())
  3870.    {
  3871.       cout << "Record #"
  3872.             << ++rec
  3873.             << ": "
  3874.             << buffer
  3875.             << endl ;
  3876.       cout << "fpm is: "
  3877.            << file_both.tellg()
  3878.            << endl ;
  3879.       file_both >> FLUSH ;
  3880.    }
  3881.  
  3882.    return 0 ;
  3883. }
  3884.  
  3885. ==========================================================
  3886.  
  3887.    This program gives the user complete flexibility as to the name of the
  3888. external file to be manipulated, and modes to be used. All such variables
  3889. are entered from the DOS command line.
  3890.  
  3891. // EXAMPLE FILEIO-05
  3892.  
  3893. // GIVE THE USER COMPLETE FLEXIBILITY
  3894. // AS TO THE MODE OF THE FILE AND THE
  3895. // DATA WRITTEN AND READ
  3896.  
  3897. // ARGUMENTS ARE ENTERED FROM THE DOS
  3898. // COMMAND LINE. THE FIRST ARGUMENT
  3899. // IS THE DISK FILE NAME, AND THE
  3900. // REMAINING ARGUMENTS REPRESENT THE
  3901. // VARIOUS OPEN MODES, EXACTLY AS
  3902. // SPECIFIED BY THE ENUMERATED TYPES
  3903.  
  3904. // NOTE THAT A CLASS IS NOW USED TO
  3905. // CONTROL THE VARIOUS OPERATIONS ON
  3906. // A FILE OBJECT
  3907.  
  3908. #include <header.h>
  3909.  
  3910. const int max = 100 ;
  3911.  
  3912. class file
  3913. {
  3914.    fstream file_object ;
  3915.      public:
  3916.  
  3917.    int open(int argc , char* argv[]) ;
  3918.    void read() ;
  3919.    void write() ;
  3920.    void beginning() ;
  3921.    void end() ;
  3922.    void print() ;
  3923.    void close() ;
  3924. } ;
  3925.  
  3926. // Open the file by setting up the
  3927. // field 'mode' with the OR of what-
  3928. // ever modes the user has chosen
  3929.  
  3930. int file::open(int argc , char* argv[])
  3931. {
  3932.    int mode = 0 ;
  3933.  
  3934.    for(int i = 2 ; i < argc ; ++i)
  3935.    {
  3936.       if(!strcmp (argv[i] , "out"))
  3937.           mode |= ios::out ;
  3938.       else if(!strcmp (argv[i] , "in"))
  3939.           mode |= ios::in ;
  3940.       else if(!strcmp (argv[i] , "app"))
  3941.           mode |= ios::app ;
  3942.       else if(!strcmp (argv[i] , "ate"))
  3943.           mode |= ios::ate ;
  3944.       else if(!strcmp (argv[i] , "trunc"))
  3945.           mode |= ios::trunc ;
  3946.       else if(!strcmp (argv[i] , "nocreate"))
  3947.           mode |= ios::nocreate ;
  3948.       else if(!strcmp (argv[i] , "noreplace"))
  3949.           mode |= ios::noreplace ;
  3950.       else if(!strcmp (argv[i] , "binary"))
  3951.           mode |= ios::binary ;
  3952.       else
  3953.           cout << "Invalid mode: "
  3954.                << argv[i]
  3955.                << endl ;
  3956.    }
  3957.  
  3958.    // Perform the actual open
  3959.    file_object.open(argv[1] , mode) ;
  3960.  
  3961.    // If an error occurred, return
  3962.    // "true"
  3963.    return (!file_object) ;
  3964. }
  3965.  
  3966. // Read the a record
  3967.  
  3968. void file::read()
  3969. {
  3970.    char buffer[max] ;
  3971.  
  3972.    cout << "Data line: " ;
  3973.    file_object.get(buffer , max) ;
  3974.    if(!(file_object.eof()))
  3975.       cout << buffer << endl ;
  3976.    else
  3977.       cout << "EOF\n" ;
  3978.  
  3979.    file_object >> FLUSH ;
  3980. }
  3981.  
  3982. // Write the file
  3983.  
  3984. void file::write()
  3985. {
  3986.    char buffer [max] ;
  3987.  
  3988.    cout << "Enter some data: " ;
  3989.    cin.get(buffer , max) ;
  3990.    cin >> FLUSH ;
  3991.    file_object << buffer << endl ;
  3992.    // Might be writing to a read-only
  3993.    // file
  3994.    file_object.clear() ;
  3995. }
  3996.  
  3997. // Return to the start of the file
  3998.  
  3999. void file::beginning()
  4000. {
  4001.    file_object.seekg(0) ;
  4002.    file_object.seekp(0) ;
  4003. }
  4004.  
  4005. // Seek to the end of the file
  4006.  
  4007. void file::end()
  4008. {
  4009.    file_object.seekg(0 , ios::end) ;
  4010.    file_object.seekp(0 , ios::end) ;
  4011. }
  4012.  
  4013. // Print the entire file
  4014.  
  4015. void file::print()
  4016. {
  4017.    long position = file_object.tellg() ;
  4018.    char buffer[max] ;
  4019.    int rec = 0 ;
  4020.    file_object.seekg(0) ;
  4021.    while(!file_object.get(buffer , max).eof())
  4022.    {
  4023.       cout << "Record #"
  4024.            << ++rec
  4025.            << ": "
  4026.            << buffer
  4027.            << endl ;
  4028.       file_object >> FLUSH ;
  4029.    }
  4030.    cout << endl ;
  4031.    file_object.seekg(position) ;
  4032.    file_object.clear() ;
  4033. }
  4034.  
  4035. // Close the file
  4036.  
  4037. void file::close()
  4038. {
  4039.    file_object.close() ;
  4040. }
  4041.  
  4042. ///////////////////////////////////
  4043.  
  4044. char menu() ;
  4045.  
  4046. int main(int argc , char* argv [])
  4047. {
  4048.    file my_file ;
  4049.  
  4050.    if(argc < 2)
  4051.    {
  4052.       cout << "NO FILE NAME\n" ;
  4053.       exit(1) ;
  4054.    }
  4055.  
  4056.    if(my_file.open(argc , argv))
  4057.    {
  4058.       cout << "OPEN FAILED\n" ;
  4059.       exit(2) ;
  4060.    }
  4061.  
  4062.    char ch ;
  4063.    while((ch = menu()) != 'X')
  4064.    {
  4065.       switch(ch)
  4066.       {
  4067.         case 'R' : my_file.read() ;
  4068.                    break ;
  4069.         case 'W' : my_file.write() ;
  4070.                    break ;
  4071.         case 'B' : my_file.beginning() ;
  4072.                    break ;
  4073.         case 'E' : my_file.end() ;
  4074.                    break ;
  4075.         case 'P' : my_file.print() ;
  4076.                    break ;
  4077.         default :  cout << "INVALID\n" ;
  4078.                    break ;
  4079.       }
  4080.    }
  4081.    my_file.close() ;
  4082.  
  4083.    return 0 ;
  4084. }
  4085.  
  4086. ///////////////////////////////////////
  4087.  
  4088. char menu()
  4089. {
  4090.    cout << "\t(R)ead a record\n" ;
  4091.    cout << "\t(W)rite a record\n" ;
  4092.    cout << "\t(B)eginning of file\n" ;
  4093.    cout << "\t(E)nd of the file\n" ;
  4094.    cout << "\t(P)rint the file\n" ;
  4095.    cout << "\te(X)it\n" ;
  4096.  
  4097.    cout << "\n\tYour choice: " ;
  4098.    char ch ;
  4099.    cin >> ch >> FLUSH ;
  4100.    return (toupper(ch)) ;
  4101. }
  4102.  
  4103. ==========================================================
  4104.  
  4105. Using the line printer
  4106.  
  4107.    The line printer is just another output file insofar as DOS is
  4108. concerned. To redirect output to a printer from within your program, use
  4109. the predefined name prn.
  4110.  
  4111. // EXAMPLE FILEIO-06
  4112.  
  4113. // HOW TO PRINT FROM WITHIN A
  4114. // PROGRAM
  4115.  
  4116. #include <header.h>
  4117.  
  4118. int main()
  4119. {
  4120.    ofstream printer ;
  4121.    // "prn" is the DOS printer
  4122.    printer.open("prn") ;
  4123.    if (!printer)
  4124.    {
  4125.      cerr << "Can't open the printer\n" ;
  4126.      exit(1) ;
  4127.    }
  4128.    printer << "This line appears"
  4129.            << " on the printer\n" ;
  4130.  
  4131.    return 0 ;
  4132. }
  4133.  
  4134.